/*
 * Version: 2.0.16
 * Build time: Fri Dec 30 2016 16:59:42 GMT+0800 (中国标准时间)
 * Copyright 2016, Alibaba
*/

/******/ (function(modules) { // webpackBootstrap
/******/ 	// The module cache
/******/ 	var installedModules = {};

/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {

/******/ 		// Check if module is in cache
/******/ 		if(installedModules[moduleId])
/******/ 			return installedModules[moduleId].exports;

/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = installedModules[moduleId] = {
/******/ 			exports: {},
/******/ 			id: moduleId,
/******/ 			loaded: false
/******/ 		};

/******/ 		// Execute the module function
/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

/******/ 		// Flag the module as loaded
/******/ 		module.loaded = true;

/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}


/******/ 	// expose the modules object (__webpack_modules__)
/******/ 	__webpack_require__.m = modules;

/******/ 	// expose the module cache
/******/ 	__webpack_require__.c = installedModules;

/******/ 	// __webpack_public_path__
/******/ 	__webpack_require__.p = "";

/******/ 	// Load entry module and return exports
/******/ 	return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {

	// webpack入口，用于打包标签引用的build文件，引入页面后会创建全局的FocusEngine对象。

	'use strict';

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

	var _libEngineJs = __webpack_require__(1);

	var _libEngineJs2 = _interopRequireDefault(_libEngineJs);

	if (!window.FocusEngine) {
	  window.FocusEngine = _libEngineJs2['default'];
	}

/***/ },
/* 1 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, '__esModule', {
	  value: true
	});

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

	var _event = __webpack_require__(2);

	var _event2 = _interopRequireDefault(_event);

	var _widget = __webpack_require__(3);

	var _widget2 = _interopRequireDefault(_widget);

	var _switch = __webpack_require__(4);

	var _switch2 = _interopRequireDefault(_switch);

	var _scroll = __webpack_require__(5);

	var _scroll2 = _interopRequireDefault(_scroll);

	var _grid = __webpack_require__(8);

	var _grid2 = _interopRequireDefault(_grid);

	var _grille = __webpack_require__(9);

	var _grille2 = _interopRequireDefault(_grille);

	var Engine = {
	  Event: _event2['default'],
	  Widget: _widget2['default'],
	  Switch: _switch2['default'],
	  Scroll: _scroll2['default'],
	  Grid: _grid2['default'],
	  Grille: _grille2['default'],
	  roles: ['Widget', 'Switch', 'Scroll', 'Grid', 'Grille'],
	  render: function render(dom, noPreventDefault) {
	    if (dom === undefined) dom = document.body;

	    var domRole = dom.getAttribute('fe-role');
	    // 如果fe-role错误，抛出
	    if (domRole && this.roles.indexOf(domRole) === -1) {
	      console.error(dom);
	      console.error('[FocusEngine_Error](' + domRole + ')不是支持的fe-role类型，只支持以下类型：' + this.roles.join('、'));
	      return;
	    }
	    // 默认Widget
	    if (!domRole) {
	      dom.setAttribute('fe-role', 'Widget');
	    }
	    // 如果该页面已经有组件树，那么只需要reRender该组件树即可
	    if (window.$FocusEngineGlobalRoot) {
	      window.$FocusEngineGlobalRoot.reRender();
	      return window.$FocusEngineGlobalRoot.getWidgetById(dom.id);
	    }
	    // 如果该页面还没有组件树，那么需要从body渲染页面组件树，然后返回dom对应的组件
	    var bodyRole = document.body.getAttribute('fe-role');
	    // 如果fe-role错误，抛出
	    if (bodyRole && this.roles.indexOf(bodyRole) === -1) {
	      console.error('[FocusEngine_Error](' + bodyRole + ')不是支持的fe-role类型，只支持以下类型：' + this.roles.join('、'));
	      return;
	    }
	    // 默认Widget
	    if (!bodyRole) {
	      document.body.setAttribute('fe-role', 'Widget');
	      bodyRole = 'Widget';
	    }
	    window.$FocusEngineGlobalRoot = new this[bodyRole](document.body);
	    window.$FocusEngineGlobalRoot.focus();
	    window.$FocusEngineGlobalRoot.handleRootEvent(noPreventDefault);
	    return window.$FocusEngineGlobalRoot.getWidgetById(dom.id);
	  },

	  // 通过dom节点创建一个widget并递归创建dom的内部widget
	  createWidget: function createWidget(dom) {
	    var domRole = dom.getAttribute('fe-role');
	    // 如果fe-role错误，抛出
	    if (domRole && this.roles.indexOf(domRole) === -1) {
	      console.error(dom);
	      console.error('[FocusEngine_Error](' + domRole + ')不是支持的fe-role类型，只支持以下类型：' + this.roles.join('、'));
	      return;
	    }
	    // 默认Widget
	    if (!domRole) {
	      dom.setAttribute('fe-role', 'Widget');
	    }
	    return new this[domRole](dom);
	  },

	  appendWidget: function appendWidget(dom) {
	    var widget = this.createWidget(dom);
	    while (dom.parentNode) {
	      dom = dom.parentNode;
	      if (!dom.getAttribute('fe-role')) {
	        continue;
	      }
	      var id = dom.id;
	      this.getWidgetById(id).addChildWidget(widget);
	      return;
	    }
	  },

	  // 获取整个页面组件树的根组件
	  getRoot: function getRoot() {
	    return window.$FocusEngineGlobalRoot;
	  },

	  getWidgetById: function getWidgetById(id) {
	    if (window.$FocusEngineGlobalRoot) {
	      return window.$FocusEngineGlobalRoot.getWidgetById(id);
	    } else {
	      return null;
	    }
	  },

	  getFocusedLeaf: function getFocusedLeaf() {
	    if (window.$FocusEngineGlobalRoot) {
	      return window.$FocusEngineGlobalRoot.getFocusedLeaf();
	    } else {
	      return null;
	    }
	  },

	  freeze: function freeze(blur) {
	    window.$FocusEngineGlobalRoot && window.$FocusEngineGlobalRoot.freeze(blur);
	  },

	  activate: function activate() {
	    window.$FocusEngineGlobalRoot && window.$FocusEngineGlobalRoot.activate();
	  },

	  disableClick: function disableClick() {
	    window.$FocusEngineGlobalRoot && window.$FocusEngineGlobalRoot.disableClick();
	  },

	  enableClick: function enableClick() {
	    window.$FocusEngineGlobalRoot && window.$FocusEngineGlobalRoot.enableClick();
	  }
	};

	exports['default'] = Engine;
	module.exports = exports['default'];

/***/ },
/* 2 */
/***/ function(module, exports) {

	"use strict";

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var Event = (function () {

	  /**
	   * type：事件类型
	   * target：触发事件的组件
	   * data：其他事件属性，如{keyCode: 13}
	   */

	  function Event(type, target, data) {
	    _classCallCheck(this, Event);

	    this.type = type;
	    this._propagationStopped = false;
	    this._defaultPrevented = false;
	    this._listenerPrevented = false;
	    if (target) {
	      this.target = target;
	    }
	    if (data) {
	      for (var pro in data) {
	        this[pro] = data[pro];
	      }
	    }
	  }

	  // 停止冒泡

	  Event.prototype.stopPropagation = function stopPropagation() {
	    this._propagationStopped = true;
	  };

	  // 该事件是否已经停止冒泡

	  Event.prototype.isPropagationStopped = function isPropagationStopped() {
	    return this._propagationStopped;
	  };

	  // 禁止默认事件

	  Event.prototype.preventDefault = function preventDefault() {
	    this._defaultPrevented = true;
	  };

	  // 是否已经禁止默认事件

	  Event.prototype.isDefaultPrevented = function isDefaultPrevented() {
	    return this._defaultPrevented;
	  };

	  // 禁止触发通过on添加的listener

	  Event.prototype.preventListener = function preventListener() {
	    this._listenerPrevented = true;
	  };

	  // 是否已经禁止Listener

	  Event.prototype.isListenerPrevented = function isListenerPrevented() {
	    return this._listenerPrevented;
	  };

	  _createClass(Event, null, [{
	    key: "VK_ENTER",
	    get: function get() {
	      return 13;
	    }
	  }, {
	    key: "VK_LEFT",
	    get: function get() {
	      return 37;
	    }
	  }, {
	    key: "VK_UP",
	    get: function get() {
	      return 38;
	    }
	  }, {
	    key: "VK_RIGHT",
	    get: function get() {
	      return 39;
	    }
	  }, {
	    key: "VK_DOWN",
	    get: function get() {
	      return 40;
	    }
	  }]);

	  return Event;
	})();

	exports["default"] = Event;
	module.exports = exports["default"];

/***/ },
/* 3 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, '__esModule', {
	  value: true
	});

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }

	var _event = __webpack_require__(2);

	var _event2 = _interopRequireDefault(_event);

	var _engine = __webpack_require__(1);

	var _engine2 = _interopRequireDefault(_engine);

	var Widget = (function () {

	  /**
	   * @param container {HTMLElement} 组件的容器dom元素
	   */

	  function Widget(container) {
	    _classCallCheck(this, Widget);

	    if (!container) {
	      console.error('[FocusEngine_Error]创建组件必须传入相应的容器元素。');
	      return;
	    }
	    this.con = container;

	    if (this.con.id) {
	      this.id = this.con.id;
	      if (document.querySelector('#' + this.id) !== this.con) {
	        console.error('[FocusEngine_Error]页面元素有重复的id(' + this.id + ')，请检查！');
	      }
	    } else {
	      // 生成随机ID
	      var randomId = Math.random().toString().slice(2, 12);
	      var confirmed = false;
	      while (!confirmed) {
	        if (document.getElementById('fe-' + randomId)) {
	          randomId = Math.random().toString().slice(2, 12);
	        } else {
	          confirmed = true;
	        }
	      }
	      this.id = 'fe-' + randomId;
	      this.con.id = this.id;
	    }
	    this.options = this._getOptions(container);
	    this.parentWidget = null;
	    this.focusedChildWidget = null;
	    this.cachedChildWidget = null;
	    this.active = true;
	    this.disabled = this.options.cfg.disable === 'yes';
	    this.noClick = this.options.cfg.disable_click === 'yes';
	    if (this.disabled) {
	      this.addClass('fe-disable');
	    }
	    this.eventListeners = [];
	    this._initChildWidgets();
	    this._getOriginalRect();
	  }

	  /**
	   * 当widget对应的dom结构发生改变时，进行重新渲染。
	   * 渲染会根据变动的dom来针对性的进行，如果某个widget的直接子widget没有变化，那么不进行rerender
	   */

	  Widget.prototype.reRender = function reRender() {
	    if (!document.querySelector('#' + this.id)) {
	      return;
	    }
	    this.con = document.querySelector('#' + this.id);
	    this.options = this._getOptions(this.con);
	    this._reRenderChildWidget();
	    this._getOriginalRect();
	  };

	  Widget.prototype._getOriginalRect = function _getOriginalRect() {
	    this.originalRect = this.getWidgetRect();
	  };

	  Widget.prototype.getFutureRect = function getFutureRect() {
	    var widget = this;
	    var rect = widget.getWidgetRect();
	    var originalRect = widget.originalRect;
	    while (widget.getParentWidget()) {
	      var _parent = widget.getParentWidget();
	      if (_parent instanceof _engine2['default'].Scroll) {
	        if (_parent.dir === 'v') {
	          rect.top = originalRect.top + _parent.futureOffset;
	          rect.bottom = originalRect.bottom + _parent.futureOffset;
	          rect.centerY = originalRect.centerY + _parent.futureOffset;
	        } else if (_parent.dir === 'h') {
	          rect.left = originalRect.left + _parent.futureOffset;
	          rect.right = originalRect.right + _parent.futureOffset;
	          rect.centerX = originalRect.centerX + _parent.futureOffset;
	        }
	      }
	      if (_parent instanceof _engine2['default'].Grid) {
	        if (_parent.horizontal) {
	          rect.left = originalRect.left + widget.futureOffset;
	          rect.right = originalRect.right + widget.futureOffset;
	          rect.centerX = originalRect.centerX + widget.futureOffset;
	        } else {
	          rect.top = originalRect.top + widget.futureOffset;
	          rect.bottom = originalRect.bottom + widget.futureOffset;
	          rect.centerY = originalRect.centerY + widget.futureOffset;
	        }
	      }
	      widget = _parent;
	    }
	    return rect;
	  };

	  Widget.prototype._reRenderChildWidget = function _reRenderChildWidget() {
	    var descendantNodes = Array.prototype.slice.call(this.con.querySelectorAll('[fe-role]'));
	    // 排除掉深层次的可初始化为组件的dom，
	    // 只保留遍历到的首层dom
	    for (var i = 0; i < descendantNodes.length; i++) {
	      var descd = descendantNodes[i];
	      var role = descd.getAttribute('fe-role');
	      if (_engine2['default'].roles.indexOf(role) === -1) {
	        console.error(descd);
	        console.error('[FocusEngine_Error](' + role + ')不是支持的fe-role类型，只支持以下类型：' + _engine2['default'].roles.join('、'));
	        continue;
	      }
	      descendantNodes = this._filterArray(descendantNodes, Array.prototype.slice.call(descendantNodes[i].querySelectorAll('[fe-role]')));
	    }

	    // 首先删除容器已经被删除的子组件
	    for (var i = 0; i < this.childWidgets.length; i++) {
	      if (descendantNodes.indexOf(this.childWidgets[i].getDOMNode()) === -1) {
	        this.removeChildWidget(i);
	        i--;
	        continue;
	      }
	      var tempRole = this.childWidgets[i].getDOMNode().getAttribute('fe-role');
	      if (_engine2['default'].roles.indexOf(tempRole) === -1 || !(this.childWidgets[i] instanceof _engine2['default'][tempRole])) {
	        this.removeChildWidget(i);
	        i--;
	      }
	    }

	    // 其次递归遍历需要保持（容器还存在）的子组件
	    for (var i = 0; i < this.childWidgets.length; i++) {
	      this.childWidgets[i].reRender();
	    }

	    // 最后创建新增加的组件，并添加到子组件中
	    for (var i = 0; i < descendantNodes.length && descendantNodes.length > this.childWidgets.length; i++) {
	      var tempNode = descendantNodes[i];
	      var alreadyHas = false;
	      for (var j = 0; j < this.childWidgets.length; j++) {
	        var tempWidget = this.childWidgets[j];
	        if (tempWidget.getDOMNode() === tempNode) {
	          alreadyHas = true;
	        }
	      }
	      if (!alreadyHas) {
	        var role = tempNode.getAttribute('fe-role');
	        if (_engine2['default'].roles.indexOf(role) !== -1) {
	          var newWidget = new _engine2['default'][role](tempNode);
	          this.addChildWidget(newWidget, i);
	        }
	      }
	    }

	    if (this.focused) {
	      this.focus(true, true);
	    }
	  };

	  // 获取整个页面组件树的根组件

	  Widget.prototype.getRoot = function getRoot() {
	    return window.$FocusEngineGlobalRoot;
	  };

	  /**
	   * 挂起组件树。
	   * @param blur {Boolean} 是否在挂起后清空焦点链路。
	   */

	  Widget.prototype.freeze = function freeze(blur) {
	    var root = this.getRoot();
	    if (!root) {
	      return this;
	    }
	    root.active = false;
	    if (blur) {
	      // 若清空焦点，记录挂起前处于焦点状态的叶子节点
	      root.focusedLeafBeforeFreeze = root.getFocusedLeaf();
	      root.blur();
	    }
	    return this;
	  };

	  // 激活组件同时还原焦点链路（若挂起时清空）

	  Widget.prototype.activate = function activate() {
	    var root = this.getRoot();
	    if (!root) {
	      return this;
	    }
	    root.active = true;
	    // 若挂起的时候有缓存焦点，激活的时候要还原缓存的焦点
	    if (root.focusedLeafBeforeFreeze) {
	      if (document.querySelector('#' + root.focusedLeafBeforeFreeze.id) === root.focusedLeafBeforeFreeze.getDOMNode()) {
	        root.focusedLeafBeforeFreeze.focus();
	      } else {
	        root.focus();
	      }
	      root.focusedLeafBeforeFreeze = null;
	    }
	    return this;
	  };

	  Widget.prototype.disable = function disable() {
	    this.disabled = true;
	    this.addClass('fe-disable');
	    return this;
	  };

	  Widget.prototype.enable = function enable() {
	    this.disabled = false;
	    this.removeClass('fe-disable');
	    return this;
	  };

	  Widget.prototype._getOptions = function _getOptions(node) {
	    var options = {};
	    this.feCfg = this._removeSpaces(node.getAttribute('fe-cfg'));
	    var cfg = {};
	    if (this.feCfg) {
	      var cfgArr = this.feCfg.split(/,|;/);
	      cfgArr.forEach(function (c) {
	        var tmpArr = c.split(':');
	        if (tmpArr.length < 2) return false;
	        tmpArr[0] = tmpArr[0].replace(/switch_|scroll_|grid_/g, '');
	        cfg[tmpArr[0]] = tmpArr[1];
	      });
	    }
	    options.cfg = cfg;
	    var dataDir = this._removeSpaces(node.getAttribute('fe-goto'));
	    var dir = {};
	    if (dataDir) {
	      var dirArr = dataDir.split(';');
	      if (dirArr[0]) dir.up = dirArr[0];
	      if (dirArr[1]) dir.right = dirArr[1];
	      if (dirArr[2]) dir.down = dirArr[2];
	      if (dirArr[3]) dir.left = dirArr[3];
	    }
	    options.dir = dir;
	    options.tab = this._removeSpaces(node.getAttribute('fe-index'));
	    return options;
	  };

	  // 遍历dom树，自动映射为组件树

	  Widget.prototype._initChildWidgets = function _initChildWidgets() {
	    this.childWidgets = [];
	    this.childMap = {};
	    var descendantNodes = Array.prototype.slice.call(this.con.querySelectorAll('[fe-role]'));
	    // 排除掉深层次的可初始化为组件的dom，
	    // 只保留遍历到的首层dom
	    for (var i = 0; i < descendantNodes.length; i++) {
	      var descd = descendantNodes[i];
	      var role = descd.getAttribute('fe-role');
	      if (_engine2['default'].roles.indexOf(role) === -1) {
	        console.error(descd);
	        console.error('[FocusEngine_Error](' + role + ')不是支持的fe-role类型，只支持以下类型：' + _engine2['default'].roles.join('、'));
	        continue;
	      }
	      descendantNodes = this._filterArray(descendantNodes, Array.prototype.slice.call(descendantNodes[i].querySelectorAll('[fe-role]')));
	    }

	    var node = undefined,
	        w = undefined;
	    for (var i = 0, j = descendantNodes.length; i < j; i++) {
	      node = descendantNodes[i];
	      // 如果fe-role为可以初始化的组件名，则初始化子组件
	      var role = node.getAttribute('fe-role');
	      if (_engine2['default'].roles.indexOf(role) !== -1) {
	        // 子组件不需要focus，但需要继续递归初始化
	        w = new _engine2['default'][role](node);
	        this.addChildWidget(w);
	      }
	    }
	  };

	  Widget.prototype.handleRootEvent = function handleRootEvent(noPreventDefault) {
	    var _this = this;

	    document.addEventListener('keydown', function (e) {
	      if (!_this.active) {
	        return;
	      }
	      e = e || window.event;

	      var k = e.keyCode,
	          l = _this.getFocusedLeaf();

	      if (k) {
	        l.fire(new _event2['default']('keydown', l, { keyCode: k }));
	        if (l && k === _event2['default'].VK_ENTER) {
	          l.fire(new _event2['default']('okdown', l, { keyCode: k }));
	        }
	        if (!noPreventDefault) {
	          e.preventDefault();
	        }
	      }
	    });

	    document.addEventListener('keyup', function (e) {
	      if (!_this.active) {
	        return;
	      }
	      e = e || window.event;

	      var k = e.keyCode,
	          l = _this.getFocusedLeaf();

	      if (k) {
	        l && l.fire(new _event2['default']('keyup', l, { keyCode: k }));
	        if (l && k === _event2['default'].VK_ENTER) {
	          l.fire(new _event2['default']('ok', l, { keyCode: k }));
	        }
	        if (!noPreventDefault) {
	          e.preventDefault();
	        }
	      }
	    });

	    document.addEventListener('click', function (e) {
	      if (!_this.active) {
	        return;
	      }
	      e = e || window.event;

	      var t = e.target;
	      var w = null;
	      while (t && t !== document) {
	        // 自下向上找到第一个组件容器
	        if (_engine2['default'].roles.indexOf(t.getAttribute('fe-role')) !== -1) {
	          w = _this.getWidgetById(t.id);
	          // 如果是叶子组件的容器，那么触发click事件并focus
	          if (w && w.isLeafWidget()) {
	            var p = w;
	            while (p) {
	              if (p.noClick) {
	                return;
	              }
	              p = p.parentWidget;
	            }
	            w && w.fire(new _event2['default']('click', w));
	            if (!noPreventDefault) {
	              e.preventDefault();
	            }
	            if (!w.disabled) {
	              if (w.focused) {
	                w.fire(new _event2['default']('ok', w, { isClick: true }));
	              } else {
	                w.focus();
	              }
	            }
	            return;
	            // 如果找到的第一个组件不是叶子组件，则不进行操作
	          } else {
	              return;
	            }
	          // 不是组件容器，继续向上查询
	        } else {
	            t = t.parentNode;
	          }
	      }
	    });
	  };

	  /**
	   * 获取当前选中的叶子节点
	   * @return {Widget | null} 组件实例
	   */

	  Widget.prototype.getFocusedLeaf = function getFocusedLeaf() {
	    if (this.isLeafWidget()) {
	      return this;
	    } else if (!this.getFocusedChildWidget()) {
	      return null;
	    } else {
	      return this.getFocusedChildWidget().getFocusedLeaf();
	    }
	  };

	  /**
	   * 为widget的容器添加类名
	   * @param className {String} 待添加的类名
	   */

	  Widget.prototype.addClass = function addClass(className) {
	    this.con.classList.add(className);
	  };

	  /**
	   * 为widget的容器删除类名
	   * @param className {String} 待删除的类名
	   */

	  Widget.prototype.removeClass = function removeClass(className) {
	    this.con.classList.remove(className);
	  };

	  /**
	   * 判断widget的容器是否有类名
	   * @param className {String} 待判断的类名
	   * @return {Boolean} 是否包含类名
	   */

	  Widget.prototype.hasClass = function hasClass(className) {
	    return this.con.classList.contains(className);
	  };

	  /**
	   * 显示组件
	   */

	  Widget.prototype.show = function show() {
	    this.con.style.display = 'block';
	  };

	  /**
	   * 隐藏组件
	   */

	  Widget.prototype.hide = function hide() {
	    this.con.style.display = 'none';
	  };

	  /**
	   * 选中当前组件，并递归选中
	   * @param {Boolean} 是否强制执行focus
	   */

	  Widget.prototype.focus = function focus(force, preventListener) {
	    if (!force && this.focused) {
	      return this;
	    }
	    // 如果不是叶子节点，找到默认的叶子节点，触发focus事件
	    var willFocusedLeaf = this;
	    while (!willFocusedLeaf.isLeafWidget()) {
	      var cache = willFocusedLeaf.getCachedChildWidget();
	      if (cache && willFocusedLeaf.options.cfg.disable_child_cache !== 'yes') {
	        willFocusedLeaf = cache;
	        continue;
	      }
	      var defaul = willFocusedLeaf.getDefaultFocusedChildWidget();
	      if (defaul) {
	        willFocusedLeaf = defaul;
	        continue;
	      }
	      var first = willFocusedLeaf.getFirstFocusableChildWidget();
	      if (first) {
	        willFocusedLeaf = first;
	        continue;
	      }
	      break;
	    }
	    var focusEvent = new _event2['default']('focus', willFocusedLeaf, { force: force });
	    if (preventListener) {
	      focusEvent.preventListener();
	    }
	    willFocusedLeaf.fire(focusEvent);
	    return this;
	  };

	  // focus时的默认处理

	  Widget.prototype.focusDefault = function focusDefault(e) {
	    if (this.focused && !e.force) {
	      return;
	    }
	    var parent = this.getParentWidget();
	    if (parent) {
	      var oldFocusedChildWidget = parent.getFocusedChildWidget();
	      if (oldFocusedChildWidget && oldFocusedChildWidget !== this) {
	        if (oldFocusedChildWidget.isLeafWidget()) {
	          e.blurLeaf = oldFocusedChildWidget;
	        } else if (oldFocusedChildWidget.getFocusedLeaf()) {
	          e.blurLeaf = oldFocusedChildWidget.getFocusedLeaf();
	        }
	        oldFocusedChildWidget.blur();
	      }
	      parent.setFocusedChildWidget(this);
	    }
	    this.addClass('fe-focus');
	    this.focused = true;
	    this.cache();
	  };

	  Widget.prototype.blur = function blur() {
	    if (!this.focused) {
	      return this;
	    }
	    var parent = this.getParentWidget();
	    parent && parent.setFocusedChildWidget(null);
	    this.removeClass('fe-focus');
	    this.focused = false;
	    var focusedChildWidget = this.getFocusedChildWidget();
	    if (focusedChildWidget) {
	      focusedChildWidget.blur();
	    }
	    this.fire(new _event2['default']('blur', this));
	    return this;
	  };

	  Widget.prototype.cache = function cache() {
	    if (this.cached) {
	      return this;
	    }
	    var parent = this.getParentWidget();
	    if (parent) {
	      var oldCacheChildWidget = parent.getCachedChildWidget();
	      if (oldCacheChildWidget) {
	        oldCacheChildWidget.removeClass('fe-cache');
	        oldCacheChildWidget.cached = false;
	      }
	      parent.setCachedChildWidget(this);
	    }
	    this.addClass('fe-cache');
	    this.cached = true;
	    return this;
	  };

	  /**
	   * 当前组件是否为叶子节点
	   * @return {Boolean} 是否为叶子节点
	   */

	  Widget.prototype.isLeafWidget = function isLeafWidget() {
	    return !this.getFirstFocusableChildWidget();
	  };

	  /**
	   * 获取父组件
	   * @return {Widget} 返回widget实例
	   */

	  Widget.prototype.getParentWidget = function getParentWidget() {
	    return this.parentWidget;
	  };

	  /**
	   * 获取当前选中的子组件
	   * @return {Widget} 返回widget实例
	   */

	  Widget.prototype.getFocusedChildWidget = function getFocusedChildWidget() {
	    if (!this.focusedChildWidget) {
	      return null;
	    }
	    if (this.childWidgets.indexOf(this.focusedChildWidget) === -1) {
	      var widgetById = this.getWidgetById(this.focusedChildWidget.id);
	      if (this.childWidgets.indexOf(widgetById) !== -1) {
	        return widgetById;
	      }
	      return null;
	    }
	    return this.focusedChildWidget;
	  };

	  Widget.prototype.setFocusedChildWidget = function setFocusedChildWidget(widget) {
	    if (widget && this.childWidgets.indexOf(widget) === -1) {
	      return;
	    }
	    this.focusedChildWidget = widget;
	  };

	  Widget.prototype.getCachedChildWidget = function getCachedChildWidget() {
	    // 没有缓存
	    if (!this.cachedChildWidget) {
	      return null;
	    }
	    // 缓存的子组件已经删除
	    if (this.childWidgets.indexOf(this.cachedChildWidget) === -1) {
	      return null;
	    }
	    // 缓存的子组件disable
	    if (this.cachedChildWidget.disabled) {
	      return null;
	    }
	    return this.cachedChildWidget;
	  };

	  Widget.prototype.setCachedChildWidget = function setCachedChildWidget(widget) {
	    if (widget && this.childWidgets.indexOf(widget) === -1) {
	      return;
	    }
	    this.cachedChildWidget = widget;
	  };

	  Widget.prototype.getDefaultFocusedChildWidget = function getDefaultFocusedChildWidget() {
	    if (!this.defaultFocusedChildWidget) {
	      return null;
	    }
	    // 默认子组件已经删除
	    if (this.childWidgets.indexOf(this.defaultFocusedChildWidget) === -1) {
	      return null;
	    }
	    // 默认子组件disable
	    if (this.defaultFocusedChildWidget.disabled) {
	      return null;
	    }
	    return this.defaultFocusedChildWidget;
	  };

	  Widget.prototype.getFirstFocusableChildWidget = function getFirstFocusableChildWidget() {
	    for (var i = 0; i < this.childWidgets.length; i++) {
	      var tempWidget = this.childWidgets[i];
	      // 子组件disable
	      if (tempWidget.disabled) {
	        continue;
	      }
	      return tempWidget;
	    }
	    return null;
	  };

	  Widget.prototype.setDefaultFocusedChildWidget = function setDefaultFocusedChildWidget(widget) {
	    if (widget && this.childWidgets.indexOf(widget) === -1) {
	      return;
	    }
	    this.defaultFocusedChildWidget = widget;
	  };

	  /**
	   * 根据id获取组件实例
	   * @param id {Number} 组件id
	   */

	  Widget.prototype.getWidgetById = function getWidgetById(id) {
	    if (this.id === id) {
	      return this;
	    }
	    if (this.childMap[id]) {
	      return this.childMap[id];
	    }
	    for (var i = 0, j = this.childWidgets.length; i < j; i++) {
	      var w = this.childWidgets[i].getWidgetById(id);
	      if (w) {
	        return w;
	      }
	    }
	    return null;
	  };

	  /**
	   * 在子组件数组的特定位置添加一个新的子组件
	   * @param widget {Widget} 组件实例，可以是继承自Widget的任意组件实例
	   * @param index {Number} 组件在组件列表的索引位置，从0开始，如果不传，默认在最后面添加
	   */

	  Widget.prototype.addChildWidget = function addChildWidget(widget, index) {
	    if (!index && index !== 0) index = this.childWidgets.length;
	    this.childWidgets.splice(index, 0, widget);
	    // 为查询效率，增加childMap
	    this.childMap[widget.id] = widget;
	    widget.parentWidget = this;
	    if (widget.options.cfg.default_focus === 'yes') {
	      this.setDefaultFocusedChildWidget(widget);
	    }
	  };

	  /**
	   * 判断widget是否在子组件中
	   * @param widget {Widget} 组件实例，可以是继承自Widget的任意组件实例
	   */

	  Widget.prototype.hasChildWidget = function hasChildWidget(widget) {
	    return this.childWidgets.indexOf(widget) !== -1;
	  };

	  /**
	   * 删除子组件数组特定位置的子组件
	   * @param widgetOrIndex {Number} 组件本身，或组件在组件列表的索引位置（从0开始）
	   * @return widget {Number} 被删除的组件
	   */

	  Widget.prototype.removeChildWidget = function removeChildWidget(widgetOrIndex) {
	    var removeArr = undefined;
	    // 如果是Widget，则查询index
	    if (widgetOrIndex instanceof Widget) {
	      widgetOrIndex = this.childWidgets.indexOf(widgetOrIndex);
	    }
	    if (widgetOrIndex < 0) {
	      return;
	    }
	    removeArr = this.childWidgets.splice(widgetOrIndex, 1);
	    var removedWidget = removeArr.length ? removeArr[0] : null;
	    if (!removedWidget) {
	      return;
	    }
	    // 从map中删除
	    delete this.childMap[removedWidget.id];
	    // 如果删除的正好是当前选中的子组件
	    if (removedWidget === this.getFocusedChildWidget()) {
	      var willFocusedWidget = this.getDefaultFocusedChildWidget() === removedWidget ? this.childWidgets[0] : this.getDefaultFocusedChildWidget();
	      willFocusedWidget.focus();
	    }
	    // 如果删除的是缓存的子组件
	    if (removedWidget === this.getCachedChildWidget()) {
	      this.cachedChildWidget = null;
	    }
	    return removedWidget;
	  };

	  /**
	   * 获取容器dom节点
	   * @return {HTMLElement}
	   */

	  Widget.prototype.getDOMNode = function getDOMNode() {
	    return this.con;
	  };

	  // 得到dom的上下左右宽高中心位置信息

	  Widget.prototype.getWidgetRect = function getWidgetRect(cache) {
	    if (cache && this.rect) {
	      return this.rect;
	    }
	    var el = this.getDOMNode();
	    var elRect = el.getBoundingClientRect();
	    this.rect = {
	      top: elRect.top,
	      bottom: elRect.bottom,
	      right: elRect.right,
	      left: elRect.left,
	      width: elRect.width,
	      height: elRect.height,
	      centerX: elRect.width / 2 + elRect.left,
	      centerY: elRect.height / 2 + elRect.top
	    };
	    return this.rect;
	  };

	  Widget.prototype.getWidgetRectAsync = function getWidgetRectAsync(cb) {
	    var _this2 = this;

	    window.requestAnimationFrame(function () {
	      var el = _this2.getDOMNode();
	      var elRect = el.getBoundingClientRect();
	      var rect = {
	        top: elRect.top,
	        bottom: elRect.bottom,
	        right: elRect.right,
	        left: elRect.left,
	        width: elRect.width,
	        height: elRect.height,
	        centerX: elRect.width / 2 + elRect.left,
	        centerY: elRect.height / 2 + elRect.top
	      };
	      _this2.rect || (_this2.rect = rect);
	      cb && cb(rect);
	    });
	  };

	  /**
	   * 增加事件监听
	   * @param type {String} 事件类型
	   * @param cb {Function} 事件回调函数
	   * @param ctx {Object} 回调函数执行上下文
	   * @param after {Bollean} 监听在默认操作之后执行
	   * @return index {Number} 返回该监听的index，可以用来解绑
	   */

	  Widget.prototype.on = function on(type, cb, ctx, after) {
	    if (type.constructor !== String) {
	      console.warn('[FocusEngine] 事件type类型必须是String');
	      return -1;
	    }
	    if (cb.constructor !== Function) {
	      console.warn('[FocusEngine] 事件监听类型必须是Function');
	      return -1;
	    }
	    type = type.toLowerCase();
	    this.eventListeners.push({
	      type: type,
	      cb: cb,
	      ctx: ctx || null,
	      after: !!after
	    });
	    return this.eventListeners.length - 1;
	  };

	  /**
	   * 移除事件监听
	   * @param index {Number} 事件index，即on方法的返回
	   */

	  Widget.prototype.off = function off(index) {
	    if (index < 0) {
	      return;
	    }
	    this.eventListeners[index] = null;
	  };

	  /**
	   * 解除事件绑定
	   * @param type {String} 事件类型
	   * @param cb {Function} 绑定事件的回调函数
	   */

	  Widget.prototype.detach = function detach(type, cb) {
	    console.warn('[FocusEngine] detach方法不再推荐使用，请使用off方法');
	    type = type.toLowerCase();
	    for (var i = 0, l = this.eventListeners.length; i < l; i++) {
	      var listener = this.eventListeners[i];
	      if (listener.type === type && listener.cb === cb) {
	        this.eventListeners[i] = null;
	      }
	    }
	  };

	  /**
	   * 触发事件，支持冒泡和捕获
	   * @param type {Event} 事件对象
	   * @param data {Object} 事件额外参数
	   */

	  Widget.prototype.fire = function fire(e) {
	    this.exeEventListeners(e);
	    this.exeEventDefault(e);
	    this.exeEventListeners(e, true);
	    var widget = this;
	    while (widget.parentWidget && !e.isPropagationStopped()) {
	      widget = widget.parentWidget;
	      widget.exeEventListeners(e);
	      widget.exeEventDefault(e);
	      widget.exeEventListeners(e, true);
	    }
	    return this;
	  };

	  // 执行自定义的事件监听

	  Widget.prototype.exeEventListeners = function exeEventListeners(e, after) {
	    // 如果阻止了Listener，那么禁止执行
	    if (e.isListenerPrevented()) {
	      return;
	    }
	    e.type = e.type.toLowerCase();
	    for (var i = 0, l = this.eventListeners.length; i < l; i++) {
	      var listener = this.eventListeners[i];
	      if (!listener) {
	        continue;
	      }
	      if (listener.type === e.type && listener.after === !!after) {
	        listener.cb.call(listener.ctx, e);
	      }
	    }
	  };

	  // 执行默认的事件处理

	  Widget.prototype.exeEventDefault = function exeEventDefault(e) {
	    // 统一管理所有的默认事件处理，任何继承Widget的组件想处理某个事件只需要增加相应的处理函数即可：
	    // 如：scrollend事件的处理函数是 scrollendDefault。
	    var eventDefaultHandler = e.type + 'Default';
	    this[eventDefaultHandler] && this[eventDefaultHandler](e);
	  };

	  /**
	   * 销毁组件及其子组件
	   * @param isClearDom {Boolean} 销毁组件的时候是否把dom架构连带销毁
	   */

	  Widget.prototype.destroy = function destroy(isClearDom) {
	    for (var i = 0; i < this.childWidgets.length; i++) {
	      this.childWidgets[i].destroy(isClearDom);
	    }
	    if (this.getParentWidget()) {
	      this.getParentWidget().removeChildWidget(this);
	    }
	    delete this.eventListeners;
	    if (isClearDom) {
	      this.con.parentNode.removeChild(this.con);
	    }
	  };

	  Widget.prototype._filterArray = function _filterArray(arr1, arr2) {
	    return arr1.filter(function (el, i, arr) {
	      return arr2.indexOf(el) === -1;
	    });
	  };

	  Widget.prototype._removeSpaces = function _removeSpaces(str) {
	    if (!str) {
	      return '';
	    }
	    return str.replace(/\s+/g, '');
	  };

	  Widget.prototype.parseDom = function parseDom(html) {
	    var tmp = document.createElement('div');
	    tmp.innerHTML = html;
	    return tmp.children;
	  };

	  Widget.prototype.disableClick = function disableClick() {
	    this.noClick = true;
	  };

	  Widget.prototype.enableClick = function enableClick() {
	    this.noClick = false;
	  };

	  // 得到组件会触发的所有事件类型

	  Widget.prototype.getEvents = function getEvents() {
	    return ['keydown', 'keyup', 'ok', 'okdown', 'click', 'focus', 'blur'];
	  };

	  return Widget;
	})();

	exports['default'] = Widget;
	module.exports = exports['default'];

/***/ },
/* 4 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, '__esModule', {
	  value: true
	});

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }

	function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

	var _widget = __webpack_require__(3);

	var _widget2 = _interopRequireDefault(_widget);

	var _event = __webpack_require__(2);

	var _event2 = _interopRequireDefault(_event);

	var Switch = (function (_Widget) {
	  _inherits(Switch, _Widget);

	  /**
	   * @param container {HTMLElement} 组件的容器dom元素
	   */

	  function Switch(container) {
	    _classCallCheck(this, Switch);

	    _Widget.call(this, container);
	    this.minInterval = this.options.cfg.interval > 0 ? this.options.cfg.interval * 1000 : 0;
	    // 配置：是否禁用区域算法
	    this.disableArea = this.options.cfg.disable_area === 'yes';
	    // 配置：是否禁用算法
	    this.disableShadow = this.options.cfg.disable_shadow === 'yes';
	    this.useLeafRect = this.options.cfg.use_leaf_rect === 'yes';
	    this.cacheRect = this.options.cfg.disable_cache_rect === 'yes' ? false : true;
	  }

	  /**
	   * 删除子组件数组特定位置的子组件，由于Switch需要处理方向缓存，增加Widget没有的逻辑
	   * @param widgetOrIndex {Number} 组件本身，或组件在组件列表的索引位置（从0开始）
	   * @return widget {Number} 被删除的组件
	   */

	  Switch.prototype.removeChildWidget = function removeChildWidget(widgetOrIndex) {
	    var removedWidget = _Widget.prototype.removeChildWidget.call(this, widgetOrIndex);
	    // 如果删除的是逆方向缓存的子组件
	    if (removedWidget === this.lastFocusedChildWidget) {
	      this.lastFocusedChildWidget = null;
	    }
	    return removedWidget;
	  };

	  Switch.prototype.keydownDefault = function keydownDefault(e) {
	    if (this.isLeafWidget()) {
	      return;
	    }
	    // 如果keydown是方向键，而且没有被阻止默认处理，则进行switch操作
	    if (!e.isDefaultPrevented() && e.target && [_event2['default'].VK_LEFT, _event2['default'].VK_RIGHT, _event2['default'].VK_UP, _event2['default'].VK_DOWN].indexOf(e.keyCode) !== -1) {
	      this.doSwitch(e);
	    }
	  };

	  // 进行switch操作

	  Switch.prototype.doSwitch = function doSwitch(e) {
	    // 如果小于设置的最低间隔时间，取消这次switch
	    var currentTime = new Date().getTime();
	    if (currentTime - this.lastKeydownTime < this.minInterval) {
	      e.preventDefault();
	      return;
	    }

	    this.lastKeydownTime = currentTime;
	    var fChildWidget = this.getFocusedChildWidget();
	    var optionDir = fChildWidget.options.dir;
	    var newFocusChildWidget = null;

	    var oppositeVK = undefined;
	    var dirName = undefined;
	    if (e.keyCode === _event2['default'].VK_LEFT) {
	      oppositeVK = _event2['default'].VK_RIGHT;
	      dirName = 'left';
	    } else if (e.keyCode === _event2['default'].VK_UP) {
	      oppositeVK = _event2['default'].VK_DOWN;
	      dirName = 'up';
	    } else if (e.keyCode === _event2['default'].VK_RIGHT) {
	      oppositeVK = _event2['default'].VK_LEFT;
	      dirName = 'right';
	    } else if (e.keyCode === _event2['default'].VK_DOWN) {
	      oppositeVK = _event2['default'].VK_UP;
	      dirName = 'down';
	    }

	    // 第一优先级：缓存
	    if (this.options.cfg.disable_cache_pre !== 'yes' && this.lastKeyCode === oppositeVK && this.lastFocusedChildWidget && !this.lastFocusedChildWidget.disabled) {
	      newFocusChildWidget = this.lastFocusedChildWidget;
	    }

	    // 第二优先级：配置
	    if (!newFocusChildWidget && optionDir && optionDir[dirName]) {
	      newFocusChildWidget = this._queryWidgetByCfg(fChildWidget, optionDir[dirName]);
	    }

	    // 第三优先级：阴影算法
	    if (!newFocusChildWidget && !this.disableShadow && fChildWidget.options.cfg.disable_self_shadow !== 'yes') {
	      newFocusChildWidget = this._queryWidgetByShadowAlgorithm(fChildWidget, dirName, e);
	    }

	    // 第四优先级：区域算法
	    if (!newFocusChildWidget && !this.disableArea && fChildWidget.options.cfg.disable_self_area !== 'yes') {
	      newFocusChildWidget = this._queryWidgetByAreaAlgorithm(fChildWidget, dirName, e);
	    }

	    if (!newFocusChildWidget) {
	      this.fire(new _event2['default']('switchend', this, { keyCode: e.keyCode }));
	      return;
	    }

	    newFocusChildWidget.focus();
	    // 如果没有配置disable_cache_pre，记录上次的焦点及按键
	    if (this.options.cfg.disable_cache_pre !== 'yes') {
	      this.lastFocusedChildWidget = fChildWidget;
	      this.lastKeyCode = e.keyCode;
	    }

	    // 不再执行后续的默认事件处理，但是会继续冒泡。
	    e.preventDefault();
	  };

	  Switch.prototype._queryWidgetByCfg = function _queryWidgetByCfg(widget, tabIndex) {
	    if (tabIndex == -1) return widget;
	    for (var i = 0, j = this.childWidgets.length; i < j; i++) {
	      var tempChild = this.childWidgets[i];
	      if (tempChild === widget) {
	        continue;
	      }
	      if (tempChild.disabled) {
	        continue;
	      }
	      if (tempChild.options.tab === tabIndex && tempChild.getDOMNode().style.display !== 'none') {
	        return this.childWidgets[i];
	      }
	    }
	    return null;
	  };

	  Switch.prototype._queryWidgetByShadowAlgorithm = function _queryWidgetByShadowAlgorithm(widget, dir, e) {
	    var currentRect = widget.getWidgetRect(this.cacheRect);
	    if ((this.useLeafRect || widget.options.cfg.use_self_leaf_rect === 'yes') && e) {
	      currentRect = e.target.getWidgetRect(this.cacheRect);
	    }
	    var resultWidget = null;
	    var dis = Infinity;
	    for (var i = 0; i < this.childWidgets.length; i++) {
	      var tempWidget = this.childWidgets[i];
	      if (tempWidget === widget) {
	        continue;
	      }
	      if (tempWidget.disabled) {
	        continue;
	      }
	      var tempWidgetRect = tempWidget.getWidgetRect(this.cacheRect);
	      if (dir === 'left' && tempWidgetRect.right < currentRect.right && tempWidgetRect.left < currentRect.left && tempWidgetRect.top < currentRect.bottom && tempWidgetRect.bottom > currentRect.top && currentRect.right - tempWidgetRect.right < dis) {
	        resultWidget = tempWidget;
	        dis = currentRect.right - tempWidgetRect.right;
	      } else if (dir === 'right' && tempWidgetRect.left > currentRect.left && tempWidgetRect.right > currentRect.right && tempWidgetRect.top < currentRect.bottom && tempWidgetRect.bottom > currentRect.top && tempWidgetRect.left - currentRect.left < dis) {
	        resultWidget = tempWidget;
	        dis = tempWidgetRect.left - currentRect.left;
	      } else if (dir === 'up' && tempWidgetRect.bottom < currentRect.bottom && tempWidgetRect.top < currentRect.top && tempWidgetRect.left < currentRect.right && tempWidgetRect.right > currentRect.left && currentRect.bottom - tempWidgetRect.bottom < dis) {
	        resultWidget = tempWidget;
	        dis = currentRect.bottom - tempWidgetRect.bottom;
	      } else if (dir === 'down' && tempWidgetRect.top > currentRect.top && tempWidgetRect.bottom > currentRect.bottom && tempWidgetRect.left < currentRect.right && tempWidgetRect.right > currentRect.left && tempWidgetRect.top - currentRect.top < dis) {
	        resultWidget = tempWidget;
	        dis = tempWidgetRect.top - currentRect.top;
	      }
	    }
	    return resultWidget;
	  };

	  Switch.prototype._queryWidgetByAreaAlgorithm = function _queryWidgetByAreaAlgorithm(widget, dir, e) {
	    var currentRect = widget.getWidgetRect(this.cacheRect);
	    if ((this.useLeafRect || widget.options.cfg.use_self_leaf_rect === 'yes') && e) {
	      currentRect = e.target.getWidgetRect(this.cacheRect);
	    }
	    var resultWidget = null;
	    var dis = Infinity;
	    for (var i = 0; i < this.childWidgets.length; i++) {
	      var tempWidget = this.childWidgets[i];
	      if (tempWidget === widget) {
	        continue;
	      }
	      if (tempWidget.disabled) {
	        continue;
	      }
	      var tempWidgetRect = tempWidget.getWidgetRect(this.cacheRect);
	      if (dir === 'left' && tempWidgetRect.right <= currentRect.left) {
	        var tempDis = Infinity;
	        if (tempWidgetRect.bottom < currentRect.top) {
	          tempDis = Math.sqrt(Math.pow(currentRect.left - tempWidgetRect.right, 2) + Math.pow(currentRect.top - tempWidgetRect.bottom, 2));
	        } else if (tempWidgetRect.top > currentRect.bottom) {
	          tempDis = Math.sqrt(Math.pow(currentRect.left - tempWidgetRect.right, 2) + Math.pow(tempWidgetRect.top - currentRect.bottom, 2));
	        } else {
	          tempDis = currentRect.left - tempWidgetRect.right;
	        }
	        if (tempDis < dis) {
	          resultWidget = tempWidget;
	          dis = tempDis;
	        }
	      } else if (dir === 'right' && tempWidgetRect.left >= currentRect.right) {
	        var tempDis = Infinity;
	        if (tempWidgetRect.bottom < currentRect.top) {
	          tempDis = Math.sqrt(Math.pow(tempWidgetRect.left - currentRect.right, 2) + Math.pow(currentRect.top - tempWidgetRect.bottom, 2));
	        } else if (tempWidgetRect.top > currentRect.bottom) {
	          tempDis = Math.sqrt(Math.pow(tempWidgetRect.left - currentRect.right, 2) + Math.pow(tempWidgetRect.top - currentRect.bottom, 2));
	        } else {
	          tempDis = tempWidgetRect.left - currentRect.right;
	        }
	        if (tempDis < dis) {
	          resultWidget = tempWidget;
	          dis = tempDis;
	        }
	      } else if (dir === 'up' && tempWidgetRect.bottom <= currentRect.top) {
	        var tempDis = Infinity;
	        if (tempWidgetRect.right < currentRect.left) {
	          tempDis = Math.sqrt(Math.pow(currentRect.top - tempWidgetRect.bottom, 2) + Math.pow(currentRect.left - tempWidgetRect.right, 2));
	        } else if (tempWidgetRect.left > currentRect.right) {
	          tempDis = Math.sqrt(Math.pow(currentRect.top - tempWidgetRect.bottom, 2) + Math.pow(tempWidgetRect.left - currentRect.right, 2));
	        } else {
	          tempDis = currentRect.top - tempWidgetRect.bottom;
	        }
	        if (tempDis < dis) {
	          resultWidget = tempWidget;
	          dis = tempDis;
	        }
	      } else if (dir === 'down' && tempWidgetRect.top >= currentRect.bottom) {
	        var tempDis = Infinity;
	        if (tempWidgetRect.right < currentRect.left) {
	          tempDis = Math.sqrt(Math.pow(tempWidgetRect.top - currentRect.bottom, 2) + Math.pow(currentRect.left - tempWidgetRect.right, 2));
	        } else if (tempWidgetRect.left > currentRect.right) {
	          tempDis = Math.sqrt(Math.pow(tempWidgetRect.top - currentRect.bottom, 2) + Math.pow(tempWidgetRect.left - currentRect.right, 2));
	        } else {
	          tempDis = tempWidgetRect.top - currentRect.bottom;
	        }
	        if (tempDis < dis) {
	          resultWidget = tempWidget;
	          dis = tempDis;
	        }
	      }
	    }
	    return resultWidget;
	  };

	  Switch.prototype.getEvents = function getEvents() {
	    return _Widget.prototype.getEvents.call(this).concat(['switchend']);
	  };

	  return Switch;
	})(_widget2['default']);

	exports['default'] = Switch;
	module.exports = exports['default'];

/***/ },
/* 5 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, '__esModule', {
	  value: true
	});

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }

	function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

	var _switch = __webpack_require__(4);

	var _switch2 = _interopRequireDefault(_switch);

	var _event = __webpack_require__(2);

	var _event2 = _interopRequireDefault(_event);

	var _animate = __webpack_require__(6);

	var _animate2 = _interopRequireDefault(_animate);

	var Scroll = (function (_Switch) {
	  _inherits(Scroll, _Switch);

	  /**
	   * @param container {HTMLElement} 组件的容器dom元素
	   */

	  function Scroll(container) {
	    var _this = this;

	    _classCallCheck(this, Scroll);

	    _Switch.call(this, container);
	    this.cacheRect = false;
	    this.dir = this.options.cfg.dir === 'h' ? this.options.cfg.dir : 'v';
	    this.centerDOM = this.options.cfg.center === 'document' ? this.options.cfg.center : 'con';
	    this.duration = this.options.cfg.duration ? parseFloat(this.options.cfg.duration) : 0.3;
	    this.speedupDuration = this.options.cfg.speedup_duration ? parseFloat(this.options.cfg.speedup_duration) : this.duration * 0.6;
	    this.easing = this.options.cfg.easing ? this.options.cfg.easing : 'ease-out';
	    this.speedupEasing = this.options.cfg.speedup_easing ? this.options.cfg.speedup_easing : 'linear';
	    this.useRAF = this.options.cfg.use_ram === 'yes' || this.options.cfg.use_raf === 'yes';
	    this.lazyload = this.options.cfg.disable_lazyload !== 'yes';
	    this.lazyloadDelay = this.options.cfg.lazyload_delay !== undefined ? parseFloat(this.options.cfg.lazyload_delay) : 0.1;
	    this.autoListWidth = this.options.cfg.auto_list_width === 'yes';
	    this.conList = this.con.querySelector('.scroll-list');
	    this.offset = 0;
	    this.desArr = [];
	    if (!this.conList) {
	      console.error('[FocusEngine_Error]Scroll组件必须含有一个类名为scroll-list的子元素。');
	      return;
	    }
	    var listStyles = getComputedStyle(this.conList);

	    if (listStyles.left !== 'auto' && parseInt(listStyles.left) !== 0 && this.dir === 'h') {
	      console.error('[FocusEngine_Error]横向Scroll容器的.scroll-list子元素不可设置left值');
	    }

	    if (listStyles.top !== 'auto' && parseInt(listStyles.top) !== 0 && this.dir === 'v') {
	      console.error('[FocusEngine_Error]纵向Scroll容器的.scroll-list子元素不可设置top值');
	    }

	    if (listStyles.position === 'static') {
	      this.conList.style.position = 'relative';
	    }
	    this._render();
	    if (this.autoListWidth) {
	      this._setAutoListWidth();
	    }
	    var defaultFocusedChild = this.getDefaultFocusedChildWidget();
	    if (defaultFocusedChild) {
	      this.scrollToWidget(defaultFocusedChild, 0);
	    }
	    if (this.lazyload) {
	      setTimeout(function () {
	        _this.loadVisibleImage();
	      }, 10);
	    }
	  }

	  // 计算容器和list的宽高

	  Scroll.prototype._computeScrollRect = function _computeScrollRect() {
	    this.conRect = this.getWidgetRect();
	    this.conWidth = this.conRect.width;
	    this.conHeight = this.conRect.height;
	    this.listRect = this.conList.getBoundingClientRect();
	    this.listWidth = this.listRect.width;
	    this.listHeight = this.listRect.height;
	    if (this.centerDOM === 'document') {
	      var docRect = document.documentElement.getBoundingClientRect();
	      if (this.dir === 'v') {
	        this.center = docRect.height / 2;
	      } else {
	        this.center = docRect.width / 2;
	      }
	    } else {
	      if (this.dir === 'v') {
	        this.center = this.conRect.height / 2;
	      } else {
	        this.center = this.conRect.width / 2;
	      }
	    }
	  };

	  // 自动设置横向列表的宽度

	  Scroll.prototype._setAutoListWidth = function _setAutoListWidth() {
	    this.rightPaddingWithUnit = this.options.cfg.right_padding;
	    this.rightPadding = 0;
	    if (this.rightPaddingWithUnit) {
	      if (this.rightPaddingWithUnit.indexOf('rem') !== -1) {
	        this.rightPadding = parseFloat(this.rightPaddingWithUnit) * parseFloat(document.querySelector('html').style.fontSize);
	      } else {
	        this.rightPadding = parseFloat(this.rightPaddingWithUnit);
	      }
	    }
	    this.conList.style.width = '99999px';
	    for (var i = 0, _length = this.childWidgets.length; i < _length; i++) {
	      var right = this.childWidgets[i].getWidgetRect().right;
	      var width = right - this.listRect.left + this.rightPadding;
	      if (width > this.listWidth) {
	        this.listWidth = width;
	      }
	    }
	    this.conList.style.width = this.listWidth + 'px';
	  };

	  Scroll.prototype.reRender = function reRender() {
	    var _this2 = this;

	    if (!document.querySelector('#' + this.id)) {
	      return;
	    }
	    this.con = document.querySelector('#' + this.id);
	    this.conList = this.con.querySelector('.scroll-list');
	    if (!this.conList) {
	      console.error('[FocusEngine_Error]Scroll组件必须含有一个类名为scroll-list的子元素。');
	      return;
	    }
	    var listStyles = getComputedStyle(this.conList);

	    if (listStyles.position === 'static') {
	      this.conList.style.position = 'relative';
	    }

	    this.options = this._getOptions(this.con);
	    this.dir = this.options.cfg.dir === 'h' ? this.options.cfg.dir : 'v';
	    this.centerDOM = this.options.cfg.center === 'ducoment' ? this.options.cfg.center : 'con';
	    this.duration = this.options.cfg.duration ? parseFloat(this.options.cfg.duration) : 0.3;
	    this.easing = this.options.cfg.easing ? this.options.cfg.easing : 'linear';
	    this.useRAF = this.options.cfg.use_ram === 'yes' || this.options.cfg.use_raf === 'yes';
	    this._render(true);
	    this._reRenderChildWidget();
	    if (this.autoListWidth) {
	      this._setAutoListWidth();
	    }
	    if (this.lazyload) {
	      setTimeout(function () {
	        _this2.loadVisibleImage();
	      }, 10);
	    }
	  };

	  Scroll.prototype._render = function _render(isReRender) {
	    var _this3 = this;

	    this._computeScrollRect();
	    if (!isReRender) {
	      if (this.dir === 'v') {
	        this.conList.style.top = '0px';
	      } else {
	        this.conList.style.left = '0px';
	      }
	    }
	    if (!this.useRAF) {
	      if (this.dir === 'v') {
	        this.conList.style.transition = 'top ' + this.duration + 's ' + this.easing;
	        this.conList.style.webkitTransition = 'top ' + this.duration + 's ' + this.easing;
	      } else {
	        this.conList.style.transition = 'left ' + this.duration + 's ' + this.easing;
	        this.conList.style.webkitTransition = 'left ' + this.duration + 's ' + this.easing;
	      }
	      if (!isReRender) {
	        // 避免首次render后也会触发scrollend事件
	        this.rendered = false;
	        this.conList.addEventListener('webkitTransitionEnd', function (e) {
	          if (e.target !== _this3.conList) {
	            return;
	          }
	            _this3.fire(new _event2['default']('scrollend', _this3));
	          _this3.rendered = true;
	        });
	        this.conList.addEventListener('transitionend', function (e) {
	          if (e.target !== _this3.conList) {
	            return;
	          }
				_this3.fire(new _event2['default']('scrollend', _this3));
	          _this3.rendered = true;
	        });
	      }
	    }
	  };

	  Scroll.prototype.focusDefault = function focusDefault(e) {
	    _Switch.prototype.focusDefault.call(this, e);
	    if (!this.getFirstFocusableChildWidget()) {
	      return;
	    }
	    if (!e.isDefaultPrevented()) {
	      // 如果这些值都是0，那么说明在focus之前是display:none的，因此focus时重新计算这些值
	      if (!this.conWidth && !this.conHeight && !this.listWidth && !this.listHeight && !this.center) {
	        this._computeScrollRect();
	        if (this.autoListWidth) {
	          this._setAutoListWidth();
	        }
	        var defaultFocusedChild = this.getDefaultFocusedChildWidget();
	        if (defaultFocusedChild) {
	          this.scrollToWidget(defaultFocusedChild, 0);
	          return;
	        }
	      }
	      this.doScroll(e);
	    }
	  };

	  Scroll.prototype.scrollstartDefault = function scrollstartDefault(e) {
	    this.loadImageTimeout && clearTimeout(this.loadImageTimeout);
	  };

	  Scroll.prototype.scrollendDefault = function scrollendDefault(e) {
	    var _this4 = this;
		  console.log('scrollendDefault start ...');
	    if (this.lazyload && e.target === this) {
	      this.loadImageTimeout = setTimeout(function () {
	        _this4.loadVisibleImage();
	      }, this.lazyloadDelay * 1000);
	    }
	  };

	  Scroll.prototype.doSwitch = function doSwitch(e) {
	    _Switch.prototype.doSwitch.call(this, e);
	  };

	  // 进行scroll操作

	  Scroll.prototype.doScroll = function doScroll(e) {
	    var fWidget = this.getFocusedChildWidget();
	    this.scrollToWidget(fWidget, this.duration, e);
	  };

	  /**
	   * 将scrolllist滚动到某个widget获取焦点时应该在的位置，但是并不会focus该widget
	   * @Param {Widget} widget 目标Widget
	   * @Param {Event} e 事件
	   */

	  Scroll.prototype.scrollToWidget = function scrollToWidget(widget, duration, e) {
	    var offset = this.computeOffsetByWidget(widget);
	    if (duration === undefined) {
	      duration = this.duration;
	    }
	    this.scrollListTo(offset, duration, e);
	    return this;
	  };

	  /**
	   * 计算滚动到某个widget时list的offset值
	   * @Param   {Widget} widget 目标Widget
	   * @Returns {Number} offset值
	   */

	  Scroll.prototype.computeOffsetByWidget = function computeOffsetByWidget(widget) {
	    if (widget.options.cfg.to_start === 'yes') {
	      return 0;
	    }
	    if (widget.options.cfg.to_end === 'yes') {
	      return this.dir === 'v' ? this.conHeight - this.listHeight : this.conWidth - this.listWidth;
	    }
	    this._computeScrollRect();
	    var dis = this.center - this._getExpectCenter(widget);
	    if (this.dir === 'v') {
	      if (dis < 0) {
	        // 如果向上滚动时下边界偏出，设置成最向上的位置，如果上次滚动已经达到顶，返回。
	        if (this.offset + dis < this.conHeight - this.listHeight) {
	          dis = this.conHeight - this.listHeight - this.offset;
	          if (dis > 0) {
	            return this.offset;
	          }
	        }
	      } else if (dis > 0) {
	        // 同上，防止上边界偏出。
	        if (this.offset * -1 < dis) {
	          dis = this.offset * -1;
	          if (dis < 0) {
	            return this.offset;
	          }
	        }
	      } else {
	        return this.offset;
	      }
	      return this.offset + dis;
	    }
	    // horizontal
	    if (dis < 0) {
	      // 如果向左滚动时下边界偏出，设置成最向左的位置，如果上次滚动已经达到顶，返回。
	      if (this.offset + dis < this.conWidth - this.listWidth) {
	        dis = this.conWidth - this.listWidth - this.offset;
	        if (dis > 0) {
	          return this.offset;
	        }
	      }
	    } else if (dis > 0) {
	      // 同上，防止向右边界偏出
	      if (this.offset * -1 < dis) {
	        dis = this.offset * -1;
	        if (dis < 0) {
	          return this.offset;
	        }
	      }
	    } else {
	      return this.offset;
	    }
	    return this.offset + dis;
	  };

	  /**
	   * 滚动scroll-list到一个位置，des是目的地位置；e是事件
	   * @Param {Number} des 目标offset值
	   * @Param {Event} e 事件
	   */

	  Scroll.prototype.scrollListTo = function scrollListTo(des, duration, e) {
	    var _this5 = this;

	    if (duration === undefined) {
	      duration = this.duration;
	    }
	    this.fire(new _event2['default']('scrollstart', this));
	    if (this.useRAF) {
	      if (e && e.type === 'focus') {
	        this.futureOffset = des;
	      }
	      this.desArr.push(des);
	      if (this.desArr.length === 1) {
	        this.doAnimate(duration, this.easing);
	      }
	    } else {
	      this.offset = des;
	      if (this.dir === 'v') {
	        this.conList.style.transition = 'top ' + duration + 's ' + this.easing;
	        this.conList.style.webkitTransition = 'top ' + duration + 's ' + this.easing;
	      } else {
	        this.conList.style.transition = 'left ' + duration + 's ' + this.easing;
	        this.conList.style.webkitTransition = 'left ' + duration + 's ' + this.easing;
	      }
	      setTimeout(function () {
	        if (_this5.dir === 'v') {
	          _this5.conList.style.transition = 'top ' + _this5.duration + 's ' + _this5.easing;
	          _this5.conList.style.webkitTransition = 'top ' + _this5.duration + 's ' + _this5.easing;
	        } else {
	          _this5.conList.style.transition = 'left ' + _this5.duration + 's ' + _this5.easing;
	          _this5.conList.style.webkitTransition = 'left ' + _this5.duration + 's ' + _this5.easing;
	        }
	      }, 1);
	      if (this.dir === 'v') {
	        this.conList.style.top = this.offset + 'px';
	      } else {
	        this.conList.style.left = this.offset + 'px';
	      }
	      if (e && e.type === 'focus') {
	        this.futureOffset = this.offset;
	      }
	    }
	    return this;
	  };

	  Scroll.prototype.doAnimate = function doAnimate(duration, easing) {
	    var _this6 = this;

	    // 如果下次动画offset地跟当前offset相同，取消这次动画
	    if (this.desArr[0] === this.offset) {
	      this.desArr.shift();
	      return;
	    }
	    var endCb = function endCb() {
	      _this6.scrollEndTimeout && clearTimeout(_this6.scrollEndTimeout);
	      _this6.offset = _this6.desArr.shift();
	      if (_this6.desArr.length > 0) {
	        _this6.doAnimate(_this6.speedupDuration, _this6.speedupEasing);
	      } else {
	        _this6.scrollEndTimeout = setTimeout(function () {
	          _this6.fire(new _event2['default']('scrollend', _this6));
	        }, 50);
	      }
	    };
	    (0, _animate2['default'])({
	      dom: this.conList,
	      style: this.dir === 'v' ? 'top' : 'left',
	      start: this.offset,
	      end: this.desArr[0],
	      duration: duration,
	      easing: easing,
	      cb: endCb
	    });
	  };

	  /**
	   *得到上次滚动结束后，widget中心点相对于con应该所在的位置（水平或垂直）。
	   *由于滚动过程中得到的位置是不准确的，而且也不是滚动结束后应该的位置，所以通过设置的offset和相对距离来计算。
	   *widgetRect.centerY - listRect.top是widget.center相对于conList的top的距离，由于两者是动画过程中同时获取的，所以动画对相对距离无影响。
	   *两者相加即滚动结束后widget.center相对于con的位置。
	   **/

	  Scroll.prototype._getExpectCenter = function _getExpectCenter(widget) {
	    var widgetRect = widget.getWidgetRect();
	    if (this.dir === 'v') {
	      return this.offset + widgetRect.centerY - this.listRect.top;
	    } else {
	      return this.offset + widgetRect.centerX - this.listRect.left;
	    }
	  };

	  Scroll.prototype.getListNode = function getListNode() {
	    return this.conList;
	  };

	  Scroll.prototype.loadVisibleImage = function loadVisibleImage() {
		  console.log('loadVisibleImage start');
	    var conRect = document.body.getBoundingClientRect();
	    var conLeft = conRect.left;
	    var conTop = conRect.top;
	    var conRight = conRect.right;
	    var conBottom = conRect.bottom;
		  console.log('conBottom == ' + conBottom + ' conRight=== ' + conRight + ' conTop ===  ' + conTop + ' conLeft === ' + conLeft);
	    var lazyImages = this.con.querySelectorAll('.fe-lazyload');
	    var _loop = function (i) {
	      var tempImage = lazyImages[i];
	      var dataSrc = tempImage.getAttribute('fe-src');
	      var rect = tempImage.getBoundingClientRect();
	      // 未加载过，而且在viewport之内，加载图片
	      if (tempImage.src !== dataSrc && !(rect.left <= conLeft && rect.right <= conLeft || rect.left >= conRight && rect.right >= conRight || rect.top >= conBottom && rect.bottom >= conBottom || rect.top <= conTop && rect.bottom <= conTop)) {
			  var hiddenImage = new Image();
	        hiddenImage.src = dataSrc;
	        hiddenImage.onload = function () {
	          tempImage.src = dataSrc;
	        };
	      }
	    };

	    for (var i = 0; i < lazyImages.length; i++) {
	      _loop(i);
	    }
	  };

	  Scroll.prototype.getEvents = function getEvents() {
	    return _Switch.prototype.getEvents.call(this).concat(['scrollstart', 'scrollend']);
	  };

	  return Scroll;
	})(_switch2['default']);

	exports['default'] = Scroll;
	module.exports = exports['default'];

/***/ },
/* 6 */
/***/ function(module, exports, __webpack_require__) {

	// requestAnimationFrame shim for Blitz
	'use strict';

	Object.defineProperty(exports, '__esModule', {
	  value: true
	});

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

	// Easing functions refer to 'http://greweb.me/2012/02/bezier-curve-based-easing-functions-from-concept-to-implementation/'

	var _bezierEasing = __webpack_require__(7);

	var _bezierEasing2 = _interopRequireDefault(_bezierEasing);

	window.requestAnimationFrame = window.requestAnimationFrame || function (operation) {
	  setTimeout(operation, 0);
	};
	var Easing = {
	  // Blitz 不支持改语法的babel翻译，用下方的实现
	  // 'ease-in': BezierEasing(0.42, 0.0, 1.00, 1.0),
	  // 'ease-out': BezierEasing(0.00, 0.0, 0.58, 1.0),
	  // 'ease-in-out': BezierEasing(0.42, 0.0, 0.58, 1.0),

	  // CSS3 Easing Functions: http://www.w3schools.com/cssref/css3_pr_transition-timing-function.asp
	  linear: function linear(t) {
	    return t;
	  },
	  'ease': _bezierEasing2['default'].apply(null, [0.25, 0.1, 0.25, 1]),
	  'ease-in': _bezierEasing2['default'].apply(null, [0.42, 0.0, 1.00, 1.0]),
	  'ease-out': _bezierEasing2['default'].apply(null, [0.00, 0.0, 0.58, 1.0]),
	  'ease-in-out': _bezierEasing2['default'].apply(null, [0.42, 0.0, 0.58, 1.0]),
	  /**
	   *自定义Bezier曲线
	   *@param arr {Array} 是四个Bezier曲线的定义值
	  **/
	  custom: function custom(arr) {
	    return _bezierEasing2['default'].apply(null, arr);
	  }
	  // 去掉下方的曲线，只用css默认支持的方式及自定义曲线
	  // easeInQuad(t) { return t*t;},
	  // easeOutQuad(t) { return t*(2-t);},
	  // easeInOutQuad(t) { return t<.5 ? 2*t*t : -1+(4-2*t)*t;},
	  // easeInCubic(t) { return t*t*t;},
	  // easeOutCubic(t) { return (--t)*t*t+1;},
	  // easeInOutCubic(t) { return t<.5 ? 4*t*t*t : (t-1)*(2*t-2)*(2*t-2)+1;},
	  // easeInQuart(t) { return t*t*t*t;},
	  // easeOutQuart(t) { return 1-(--t)*t*t*t;},
	  // easeInOutQuart(t) { return t<.5 ? 8*t*t*t*t : 1-8*(--t)*t*t*t;},
	  // easeInQuint(t) { return t*t*t*t*t;},
	  // easeOutQuint(t) { return 1+(--t)*t*t*t*t;},
	  // easeInOutQuint(t) { return t<.5 ? 16*t*t*t*t*t : 1+16*(--t)*t*t*t*t;},
	};

	// let frameTime = window.yunos ? 16 : 10;
	// let a = Date.now();
	// const setFrameTime = () => {
	//   const b = Date.now();
	//   frameTime = b - a;
	//   console.log(frameTime);
	//   a = b;
	//   window.requestAnimationFrame(setFrameTime);
	// };
	// window.requestAnimationFrame(setFrameTime);

	/**
	 * DOM动画函数，
	 * 暂仅支持以数字加单位为值的属性，如top、width等，不支持transform类似的属性。
	 * 暂仅支持一次缓动一个属性。
	 * @Param {Object} cfg 具体动画配置;
	 * @Param {HTMLElement} cfg.dom DOM对象；
	 * @Param {String} cfg.style style属性；
	 * @Param {String} cfg.transitionType 使用何种方式实现动画，目前支持'css'和'js'两种，默认'js'；
	 * @Param {Number} cfg.start 起始值；
	 * @Param {Number} cfg.end 结束值；
	 * @Param {String} [cfg.unit] 单位，默认px；
	 * @Param {Number} [cfg.duration] 执行动画需要的时间，以秒为单位，默认1；
	 * @Param {String} [cfg.easing] 缓动函数，目前支持：'ease'（默认）、'ease-out'、'ease-in'、'linear'；
	 * @Param {Function} [cfg.cb] 动画结束后的回调函数；
	 */
	function animate(cfg) {
	  if (!(cfg && cfg.dom && cfg.style && cfg.end !== undefined)) {
	    console.error('[FocusEngine_Error]animate方法的cfg参数：dom、style、end必需！');
	    return;
	  }
	  var dom = cfg.dom;
	  var style = cfg.style;
	  var transitionType = cfg.transitionType === 'css' ? 'css' : 'js';
	  var start = cfg.start;
	  if (start === undefined) {
	    var computedValue = parseFloat(getComputedStyle(dom)[style]);
	    start = isNaN(computedValue) ? computedValue : 0;
	  }
	  var end = cfg.end;
	  var duration = cfg.duration !== undefined ? parseFloat(cfg.duration) : 0.3;
	  var milliDuration = duration * 1000;
	  var easing = cfg.easing || 'ease-out';
	  var unit = cfg.unit || 'px';
	  var cb = cfg.cb || null;

	  // 如果使用css的方式执行动画
	  if (transitionType === 'css') {
	    var _ret = (function () {
	      var easingFunction = '';
	      if (easing.constructor === Array) {
	        easingFunction = 'cubic-bezier(' + easing.join(',') + ')';
	      } else if (easing.constructor === String) {
	        easingFunction = easing;
	      }
	      var transitionendFunc = function transitionendFunc(e) {
	        if (e.target === dom) {
	          dom.style.transition = '';
	          dom.removeEventListener('transitionend', transitionendFunc);
	          cb && cb();
	        }
	      };
	      dom.addEventListener('transitionend', transitionendFunc);
	      dom.style.transition = style + ' ' + duration + 's ' + easingFunction;
	      dom.style[style] = end + unit;
	      return {
	        v: undefined
	      };
	    })();

	    if (typeof _ret === 'object') return _ret.v;
	  }

	  // 如果使用js的方式执行动画，默认
	  var easingFunction = null;
	  if (easing.constructor === Array) {
	    easingFunction = Easing.custom(easing);
	  } else if (easing.constructor === String) {
	    easingFunction = Easing[easing];
	  }
	  // 最后权衡：使用requestAnimationFrame／依赖帧的方式
	  var allFrames = milliDuration / 14;
	  var currentFrame = 1;
	  // const startTime = Date.now();
	  var doAnimate = function doAnimate() {
	    // 每帧都获取时间在Blitz上对动画性能影响较大，因此还是按照帧数来动画
	    // const now = Date.now();
	    if (currentFrame > allFrames) {
	      dom.style[style] = end + unit;
	      cb && cb();
	    } else {
	      var percent = easingFunction(currentFrame / allFrames);
	      var currentValue = start + percent * (end - start);
	      dom.style[style] = currentValue + unit;
	      currentFrame++;
	      window.requestAnimationFrame(doAnimate);
	    }
	  };
	  window.requestAnimationFrame(doAnimate);

	  /*
	  每个动画使用单一setInterval的方式
	  const minInterval = window.yunos ? 0 : 14;
	  const interval = setInterval(() => {
	    if (currentFrame >= allFrames) {
	      clearInterval(interval);
	      dom.style[style] = end + unit;
	      cb && cb();
	    } else {
	      const percent = easingFunction(currentFrame / allFrames);
	      const currentValue = start + percent * (end - start);
	      dom.style[style] = currentValue + unit;
	      currentFrame++;
	    }
	  }, minInterval);
	  */

	  /*
	  全局单一interval的方式
	  aniArr.push({
	    easingFunction,
	    dom,
	    style,
	    unit,
	    start,
	    end,
	    change: end - start,
	    milliDuration,
	    cb,
	    startTime: Date.now()
	  });
	   if (!aniInterval) {
	    aniInterval = setInterval(() => {
	      const now = Date.now();
	      let aniLen = aniArr.length;
	      let index = 0;
	      while(index < aniLen) {
	        const tempAni = aniArr[index];
	        const past = now - tempAni.startTime;
	        if (past < tempAni.milliDuration) {
	          const percent = tempAni.easingFunction(past / tempAni.milliDuration);
	          tempAni.dom.style[tempAni.style] = tempAni.start + (percent * tempAni.change) + tempAni.unit;
	          index++;
	          continue;
	        }
	        tempAni.dom.style[tempAni.style] = tempAni.end + tempAni.unit;
	        setTimeout(() => {
	          tempAni.cb && tempAni.cb();
	        }, 0);
	        aniArr.splice(index, 1);
	        aniLen--;
	        if (aniLen === 0) {
	          clearInterval(aniInterval);
	          aniInterval = null;
	        }
	      }
	    }, window.yonos ? 0 : 10);
	  }
	  */
	}
	window.animate = animate;

	exports['default'] = animate;
	module.exports = exports['default'];

/***/ },
/* 7 */
/***/ function(module, exports) {

	/**
	 * https://github.com/gre/bezier-easing
	 * BezierEasing - use bezier curve for transition easing function
	 * by Gaëtan Renaudeau 2014 - 2015 – MIT License
	 */

	// These values are established by empiricism with tests (tradeoff: performance VS precision)
	'use strict';

	var NEWTON_ITERATIONS = 4;
	var NEWTON_MIN_SLOPE = 0.001;
	var SUBDIVISION_PRECISION = 0.0000001;
	var SUBDIVISION_MAX_ITERATIONS = 10;

	var kSplineTableSize = 11;
	var kSampleStepSize = 1.0 / (kSplineTableSize - 1.0);

	var float32ArraySupported = typeof Float32Array === 'function';

	function A(aA1, aA2) {
	  return 1.0 - 3.0 * aA2 + 3.0 * aA1;
	}
	function B(aA1, aA2) {
	  return 3.0 * aA2 - 6.0 * aA1;
	}
	function C(aA1) {
	  return 3.0 * aA1;
	}

	// Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.
	function calcBezier(aT, aA1, aA2) {
	  return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT;
	}

	// Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2.
	function getSlope(aT, aA1, aA2) {
	  return 3.0 * A(aA1, aA2) * aT * aT + 2.0 * B(aA1, aA2) * aT + C(aA1);
	}

	function binarySubdivide(aX, aA, aB, mX1, mX2) {
	  var currentX,
	      currentT,
	      i = 0;
	  do {
	    currentT = aA + (aB - aA) / 2.0;
	    currentX = calcBezier(currentT, mX1, mX2) - aX;
	    if (currentX > 0.0) {
	      aB = currentT;
	    } else {
	      aA = currentT;
	    }
	  } while (Math.abs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS);
	  return currentT;
	}

	function newtonRaphsonIterate(aX, aGuessT, mX1, mX2) {
	  for (var i = 0; i < NEWTON_ITERATIONS; ++i) {
	    var currentSlope = getSlope(aGuessT, mX1, mX2);
	    if (currentSlope === 0.0) {
	      return aGuessT;
	    }
	    var currentX = calcBezier(aGuessT, mX1, mX2) - aX;
	    aGuessT -= currentX / currentSlope;
	  }
	  return aGuessT;
	}

	module.exports = function bezier(mX1, mY1, mX2, mY2) {
	  if (!(0 <= mX1 && mX1 <= 1 && 0 <= mX2 && mX2 <= 1)) {
	    throw new Error('bezier x values must be in [0, 1] range');
	  }

	  // Precompute samples table
	  var sampleValues = float32ArraySupported ? new Float32Array(kSplineTableSize) : new Array(kSplineTableSize);
	  if (mX1 !== mY1 || mX2 !== mY2) {
	    for (var i = 0; i < kSplineTableSize; ++i) {
	      sampleValues[i] = calcBezier(i * kSampleStepSize, mX1, mX2);
	    }
	  }

	  function getTForX(aX) {
	    var intervalStart = 0.0;
	    var currentSample = 1;
	    var lastSample = kSplineTableSize - 1;

	    for (; currentSample !== lastSample && sampleValues[currentSample] <= aX; ++currentSample) {
	      intervalStart += kSampleStepSize;
	    }
	    --currentSample;

	    // Interpolate to provide an initial guess for t
	    var dist = (aX - sampleValues[currentSample]) / (sampleValues[currentSample + 1] - sampleValues[currentSample]);
	    var guessForT = intervalStart + dist * kSampleStepSize;

	    var initialSlope = getSlope(guessForT, mX1, mX2);
	    if (initialSlope >= NEWTON_MIN_SLOPE) {
	      return newtonRaphsonIterate(aX, guessForT, mX1, mX2);
	    } else if (initialSlope === 0.0) {
	      return guessForT;
	    } else {
	      return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize, mX1, mX2);
	    }
	  }

	  return function BezierEasing(x) {
	    if (mX1 === mY1 && mX2 === mY2) {
	      return x; // linear
	    }
	    // Because JavaScript number are imprecise, we should guarantee the extremes are right.
	    if (x === 0) {
	      return 0;
	    }
	    if (x === 1) {
	      return 1;
	    }
	    return calcBezier(getTForX(x), mY1, mY2);
	  };
	};

/***/ },
/* 8 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, '__esModule', {
	  value: true
	});

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }

	function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

	var _widget = __webpack_require__(3);

	var _widget2 = _interopRequireDefault(_widget);

	var _event = __webpack_require__(2);

	var _event2 = _interopRequireDefault(_event);

	var _animate = __webpack_require__(6);

	var _animate2 = _interopRequireDefault(_animate);

	var Grid = (function (_Widget) {
	  _inherits(Grid, _Widget);

	  function Grid(container) {
	    _classCallCheck(this, Grid);

	    _Widget.call(this, container);
	    this._init();
	    this._writeGridInnerHTML();
	    // 初始化子组件
	    _Widget.prototype._initChildWidgets.call(this);
	    this['_checkWidgets_' + this.dir]();
	  }

	  Grid.prototype._initChildWidgets = function _initChildWidgets() {
	    return;
	  };

	  // 判断grid是否需要reRender比较特殊，需要特殊处理

	  Grid.prototype.reRender = function reRender() {}
	  // if (!document.querySelector('#' + this.id)) {
	  //   return;
	  // }
	  // this.con = document.querySelector('#' + this.id);
	  // const firstChildWidget = this.childWidgets[0];
	  // const firstChildNode = this.getDOMNode().children[0];
	  // let needReRender = false;
	  // // 判断第一个子dom是否还是原来的dom，如果是，则用原来的templateHTML，如果不是，用新的templateHTML
	  // if (firstChildNode !== firstChildWidget.getDOMNode()) {
	  //   this.templateHTML = firstChildNode.outerHTML;
	  //   needReRender = true;
	  // }
	  // // 比较fe-cfg的几个属性，如果有改变，则需要reRender
	  // const options = this._getOptions(this.con);
	  // if (this.options.cfg.dir !== options.cfg.dir ||
	  //     this.options.cfg.row !== options.cfg.row ||
	  //     this.options.cfg.col !== options.cfg.col
	  // ) {
	  //   this.options = options;
	  //   needReRender = true;
	  // }
	  // if (!needReRender) {
	  //   return;
	  // }
	  // this.setCachedChildWidget(null);
	  // this.setFocusedChildWidget(null);
	  // this._init();
	  // this._writeGridInnerHTML();
	  // super._initChildWidgets();
	  // this[`_checkWidgets_${this.dir}`]();
	  // if (this.focused) {
	  //   this.focus(true);
	  // }

	  // 设置用户配置内容并初始化Grid
	  ;

	  Grid.prototype._init = function _init() {
	    this.dir = this.options.cfg.dir === 'h' ? 'h' : 'v';
	    this.style = this.options.cfg.dir === 'h' ? 'left' : 'top';
	    // Grid初始化
	    if (isNaN(this.options.cfg.row) || isNaN(this.options.cfg.col)) {
	      console.error('[FocusEngine_Error]Grid组件必须设置行和列！行列数为视口内可见的最多行列数。');
	      return;
	    }
	    this.duration = this.options.cfg.duration !== undefined ? parseFloat(this.options.cfg.duration) : 0.3;
	    this.speedupDuration = this.options.cfg.speedup_duration !== undefined ? parseFloat(this.options.cfg.speedup_duration) : this.duration * 0.6;
	    this.easing = this.options.cfg.easing ? this.options.cfg.easing : 'ease-out';
	    this.speedupEasing = this.options.cfg.speedup_easing ? this.options.cfg.speedup_easing : 'linear';
	    this.delay = this.options.cfg.delay !== undefined ? parseFloat(this.options.cfg.delay) : 0;
	    this.noEmpty = this.options.cfg.no_empty === 'yes';
	    if (this.delay > 0 && this.delay < 0.05) {
	      // 限制最小delay
	      this.delay = 0.05;
	    }
	    this.delayStyle = this.options.cfg.delay_style === '1' ? 1 : 0;
	    // grid对应的列表数据
	    this.data = this.data || [];
	    // 内容的渲染器
	    this.itemRender = this.itemRender || null;
	    // 是否正在滚动中
	    this.scrolling = false;
	    // 居中原点数，如果是1，则每次都居中对齐，如果是2，则两排对齐。
	    this.originSize = this.options.cfg.origin_size ? parseInt(this.options.cfg.origin_size) : 1;
	    this.origin = 0;
	    // 当前widget对应的数据
	    this.dataIndex = 0;
	    this['_init_more_' + this.dir]();
	  };

	  Grid.prototype._init_more_v = function _init_more_v() {
	    this.row = parseInt(this.options.cfg.row) + 2;
	    this.col = parseInt(this.options.cfg.col);
	    // 如果是设置居中原点数，那么行数必须等于排数，强制相等
	    if (this.originSize > 1) {
	      this.row = this.originSize + 2;
	      // 如果是居中对齐，则行数必须是奇数才可，强制设置为奇数
	    } else if (this.row % 2 === 0) {
	        this.row++;
	      }
	    this.upRow = 0;
	    this.downRow = this.row - 1;
	  };

	  Grid.prototype._init_more_h = function _init_more_h() {
	    this.row = parseInt(this.options.cfg.row);
	    this.col = parseInt(this.options.cfg.col) + 2;
	    // 如果是设置居中原点数，那么行数必须等于排数，强制相等
	    if (this.originSize > 1) {
	      this.col = this.originSize + 2;
	      // 如果是居中对齐，则列数必须是奇数才可，强制设置为奇数
	    } else if (this.col % 2 === 0) {
	        this.col++;
	      }
	    this.lefCol = 0;
	    this.rightCol = this.col - 1;
	  };

	  // 根据第一个子元素来写grid的子组件html

	  Grid.prototype._writeGridInnerHTML = function _writeGridInnerHTML() {
	    var templateDOM = this.con.children[0];
	    templateDOM.id = '';
	    this.templateHTML = templateDOM.outerHTML;
	    this.con.innerHTML = '';
	    this['_writeGridInnerHTML_' + this.dir]();
	  };

	  Grid.prototype._writeGridInnerHTML_v = function _writeGridInnerHTML_v() {
	    var rowHTML = '';
	    for (var i = 0; i < this.col; i++) {
	      rowHTML += this.templateHTML;
	    }
	    rowHTML += '<div style="clear:both;"></div>';
	    for (var i = 0; i < this.row; i++) {
	      var rowDom = document.createElement('div');
	      rowDom.innerHTML = rowHTML;
	      rowDom.style.position = 'relative';
	      // 先设置隐藏，等setData后再显示
	      // rowDom.style.opacity = 0;
	      this.con.appendChild(rowDom);
	    }
	  };

	  Grid.prototype._writeGridInnerHTML_h = function _writeGridInnerHTML_h() {
	    var colHTML = '';
	    for (var i = 0; i < this.row; i++) {
	      colHTML += this.templateHTML + '<div style="clear:both;"></div>';
	    }
	    var listDom = document.createElement('div');
	    listDom.style.width = '99999px';
	    listDom.style.height = '100%';
	    for (var i = 0; i < this.col; i++) {
	      var colDom = document.createElement('div');
	      colDom.innerHTML = colHTML;
	      colDom.style.position = 'relative';
	      colDom.style.float = 'left';
	      // 先设置隐藏，等setData后再显示
	      // colDom.style.opacity = 0;
	      listDom.appendChild(colDom);
	    }
	    listDom.appendChild(this.parseDom('<div style="clear:both;"></div>')[0]);
	    this.con.appendChild(listDom);
	  };

	  // 渲染并检查子组件

	  Grid.prototype._checkWidgets_v = function _checkWidgets_v() {
	    // chidWidgets的二维数组
	    this.widgetArr = [];
	    var j = 0;
	    for (var i = 0, l = this.childWidgets.length; i < l; i += this.col) {
	      var rowArr = this.childWidgets.slice(i, i + this.col);
	      rowArr = rowArr.map(function (v, k) {
	        v.row = j;
	        v.col = k;
	        return v;
	      });
	      this.widgetArr.push(rowArr);
	      j++;
	    }
	    var conRect = this.getWidgetRect();
	    // 容器的高度
	    this.conHeight = conRect.height;
	    // grid子组件行高，即上下两个组件中心点之间的纵向距离
	    this.rowHeight = this.childWidgets[0].con.parentNode.getBoundingClientRect().height;
	    // 选中的组件的排列位置数组，如果是1，那么都是以中心居中排列，如果是2，则两行排列
	    this.originArr = [];
	    if (this.originSize === 1) {
	      this.originArr.push(this.conHeight / 2);
	    } else {
	      for (var i = 0, halfHeight = this.rowHeight / 2; i < this.originSize; i++) {
	        this.originArr.push(halfHeight + i * this.rowHeight);
	      }
	    }
	    // 当前widget
	    this.curWid = this.childWidgets[0];
	    // 检查子组件
	    for (var i = 0; i < this.childWidgets.length; i++) {
	      var widget = this.childWidgets[i];
	      var styles = getComputedStyle(widget.getDOMNode());
	      // 初始时该widget的中心点距顶部距离
	      widget.oriOffsetCY = widget.getWidgetRect().centerY - conRect.top;
	      widget.oriCenteY = widget.oriOffsetCY;
	      // 纪录当前offset
	      widget.offset = 0;
	      widget.animationArr = [];
	      widget.isEmpty = true;
	      // 相对于当前中的子组件，组件的行数，负代表在上方，正代表在下方
	      widget.offsetRow = widget.row;
	      widget.whichData = i;
	    }
	  };

	  // 渲染并检查子组件

	  Grid.prototype._checkWidgets_h = function _checkWidgets_h() {
	    // chidWidgets的二维数组
	    this.widgetArr = [];
	    var j = 0;
	    for (var i = 0, l = this.childWidgets.length; i < l; i += this.row) {
	      var rowArr = this.childWidgets.slice(i, i + this.row);
	      rowArr = rowArr.map(function (v, k) {
	        v.col = j;
	        v.row = k;
	        return v;
	      });
	      this.widgetArr.push(rowArr);
	      j++;
	    }
	    var conRect = this.getWidgetRect();
	    // 容器的宽度
	    this.conWidth = conRect.width;
	    // grid子组件列宽，即左右两个组件中心点之间的横向距离
	    this.colWidth = this.childWidgets[0].con.parentNode.getBoundingClientRect().width;
	    // 选中的组件的排列位置数组，如果是1，那么都是以中心居中排列，如果是2，则两行排列
	    this.originArr = [];
	    if (this.originSize === 1) {
	      this.originArr.push(this.conWidth / 2);
	    } else {
	      for (var i = 0, halfWidth = this.colWidth / 2; i < this.originSize; i++) {
	        this.originArr.push(halfWidth + i * this.colWidth);
	      }
	    }
	    // 当前widget
	    this.curWid = this.childWidgets[0];
	    // 检查子组件
	    for (var i = 0; i < this.childWidgets.length; i++) {
	      var widget = this.childWidgets[i];
	      var styles = getComputedStyle(widget.getDOMNode());
	      // 初始时该widget的中心点距左侧距离
	      widget.oriOffsetCX = widget.getWidgetRect().centerX - conRect.left;
	      widget.oriCenteX = widget.oriOffsetCX;
	      // 纪录当前offset
	      widget.offset = 0;
	      widget.animationArr = [];
	      widget.isEmpty = true;
	      // 相对于当前中的子组件，组件的列数，负代表在左侧，正代表在右侧
	      widget.offsetCol = widget.col;
	      widget.whichData = i;
	    }
	  };

	  Grid.prototype.keydownDefault = function keydownDefault(e) {
	    if (this.stopSwitch) {
	      e.preventDefault();
	      return;
	    }
	    if (e.isDefaultPrevented()) {
	      return;
	    }
	    this['_keydownDefault_' + this.dir](e);
	  };

	  Grid.prototype._keydownDefault_v = function _keydownDefault_v(e) {
	    var nexIndex = this._getNextDataIndex_v(e.keyCode);
	    if (nexIndex !== -1) {
	      e.preventDefault();
	      var nexFocWid = this.childWidgets[Math.floor(nexIndex / this.col) % this.row * this.col + nexIndex % this.col];
	      nexFocWid.focus();
	    }
	  };

	  Grid.prototype._keydownDefault_h = function _keydownDefault_h(e) {
	    var nexIndex = this._getNextDataIndex_h(e.keyCode);
	    if (nexIndex !== -1) {
	      e.preventDefault();
	      var nexFocWid = this.childWidgets[Math.floor(nexIndex / this.row) % this.col * this.row + nexIndex % this.row];
	      nexFocWid.focus();
	    }
	  };

	  Grid.prototype._getNextDataIndex_v = function _getNextDataIndex_v(keyCode) {
	    var nexIndex = this.dataIndex;
	    // 向左
	    if (keyCode === _event2['default'].VK_LEFT) {
	      if (nexIndex % this.col !== 0) {
	        return --nexIndex;
	      }
	      return -1;
	    }
	    if (keyCode === _event2['default'].VK_RIGHT) {
	      if (nexIndex % this.col !== this.col - 1 && nexIndex + 1 < this.data.length) {
	        return ++nexIndex;
	      }
	      return -1;
	    }
	    if (keyCode === _event2['default'].VK_UP) {
	      if (nexIndex >= this.col) {
	        return nexIndex -= this.col;
	      }
	      return -1;
	    }
	    if (keyCode === _event2['default'].VK_DOWN) {
	      if (nexIndex + this.col < this.data.length) {
	        return nexIndex += this.col;
	      }
	      if (nexIndex + this.col >= this.data.length && Math.floor(nexIndex / this.col) < Math.floor((this.data.length - 1) / this.col)) {
	        return this.data.length - 1;
	      }
	      this.fire(new _event2['default']('reachend', this));
	      return -1;
	    }
	    return -1;
	  };

	  Grid.prototype._getNextDataIndex_h = function _getNextDataIndex_h(keyCode) {
	    var nexIndex = this.dataIndex;
	    // 向左
	    if (keyCode === _event2['default'].VK_LEFT) {
	      if (nexIndex >= this.row) {
	        return nexIndex -= this.row;
	      }
	      return -1;
	    }
	    if (keyCode === _event2['default'].VK_RIGHT) {
	      if (nexIndex + this.row < this.data.length) {
	        return nexIndex += this.row;
	      }
	      if (nexIndex + this.row >= this.data.length && Math.floor(nexIndex / this.row) < Math.floor((this.data.length - 1) / this.row)) {
	        return this.data.length - 1;
	      }
	      this.fire(new _event2['default']('reachend', this));
	      return -1;
	    }
	    if (keyCode === _event2['default'].VK_UP) {
	      if (nexIndex % this.row !== 0) {
	        return --nexIndex;
	      }
	      return -1;
	    }
	    if (keyCode === _event2['default'].VK_DOWN) {
	      if (nexIndex % this.row !== this.row - 1 && nexIndex + 1 < this.data.length) {
	        return ++nexIndex;
	      }
	      return -1;
	    }
	    return -1;
	  };

	  Grid.prototype.focusDefault = function focusDefault(e) {
	    _Widget.prototype.focusDefault.call(this, e);
	    // 如果是setData调用，那么只需要更改focus状态，无需移动
	    if (this.isSetData) {
	      return;
	    }
	    // focus时监测一次容器宽高，如果都是0，说明focus前是display:none，需要重新_checkWidgets
	    if (!this.conHeight && !this.conWidth) {
	      this['_checkWidgets_' + this.dir]();
	    }
	    this['_focusDefault_' + this.dir](e);
	  };

	  Grid.prototype._focusDefault_v = function _focusDefault_v(e) {
	    var nexWid = this.getFocusedChildWidget();
	    this.dataIndex = nexWid.whichData;
	    this.curWid = nexWid;
	    // 如果左右切换，则不滚动
	    if (nexWid.offsetRow === 0) {
	      return;
	    }
	    this._computeGridStatus_v(nexWid);
	    this._computeAllWidgetStatus_v(nexWid);
	    this._triggerWidgetsAnimation_v(nexWid);
	  };

	  Grid.prototype._focusDefault_h = function _focusDefault_h(e) {
	    var nexWid = this.getFocusedChildWidget();
	    this.dataIndex = nexWid.whichData;
	    this.curWid = nexWid;
	    // 如果上下切换，则不滚动
	    if (nexWid.offsetCol === 0) {
	      return;
	    }
	    this._computeGridStatus_h(nexWid);
	    this._computeAllWidgetStatus_h(nexWid);
	    this._triggerWidgetsAnimation_h(nexWid);
	  };

	  // 根据焦点widget计算纵向Grid滚动的一些状态：
	  // 1. 是向上还是向下滚动；2. 滚动结束后上下各有多少行；3. 焦点组件的位置

	  Grid.prototype._computeGridStatus_v = function _computeGridStatus_v(curWid) {
	    // 如果是setData调用，那么一些属性不需要再次计算
		  if (!this.isSetData) {
	      // 确定是向上还是向下滚动
			console.log("curWid.offsetRow == " + curWid.offsetRow);
	      this.isUp = curWid.offsetRow < 0;
	      // 确定下次focus子组件的origin
	      if (this.isUp && this.origin > 0) {
	        this.origin--;
	      } else if (!this.isUp && this.origin < this.originArr.length - 1) {
	        this.origin++;
	      }
	    }
		  console.log(this.origin + "   length === " + this.originArr.length);

	    // 选中的组件的中心点应在的位置
	    this.focsedCY = this.originArr[this.origin];
		  console.log("   this.focsedCY === " + this.focsedCY);
	    // 确定滚动结束后当前选中的行上下各应该有多少行
	    // 没有设置originSize的情况
	    if (this.originSize === 1) {
	      this.upRow = Math.floor(this.row / 2);
	      this.downRow = Math.floor(this.row / 2);
	      var curDataRow = Math.floor(this.dataIndex / this.col);
	      var lastDataRow = Math.floor((this.data.length - 1) / this.col);
	      var tempFocsedCY = this.focsedCY;
	      // 到达底部的情况
	      var downOffset = (lastDataRow - curDataRow) * this.rowHeight + this.rowHeight / 2;
	      if (downOffset < tempFocsedCY) {
	        this.focsedCY = this.conHeight - downOffset;
	        this.downRow = lastDataRow - curDataRow;
	        this.upRow = this.row - 1 - this.downRow;
	      }
	      // 到达顶部的情况，如果同时到达顶部和底部，则按顶部算
	      var upOffset = curDataRow * this.rowHeight + this.rowHeight / 2;
	      var listHeight = (lastDataRow + 1) * this.rowHeight;
	      if (upOffset < tempFocsedCY || listHeight < this.conHeight) {
	        this.focsedCY = upOffset;
	        this.upRow = curDataRow;
	        this.downRow = this.row - 1 - this.upRow;
	        return;
	      }
	      // 设置originSize的情况
	    } else {
	        this.upRow = this.origin + 1;
	        this.downRow = this.originSize - this.origin;
	        // 到达顶部的情况
	        if (Math.floor(this.dataIndex / this.col) === 0) {
	          this.upRow = 0;
	          this.downRow = this.row - 1;
	          return;
	        }
	        // 到达底部的情况
	        if (Math.floor(this.dataIndex / this.col) === Math.floor((this.data.length - 1) / this.col)) {
	          this.upRow = this.row - 1;
	          this.downRow = 0;
	        }
	      }
	  };

	  // 根据焦点widget计算横向Grid滚动的一些状态：
	  // 1. 是向左还是向右滚动；2. 滚动结束后左右各有多少列；3. 焦点组件的位置

	  Grid.prototype._computeGridStatus_h = function _computeGridStatus_h(curWid) {
	    // 如果是setData调用，那么一些属性不需要再次计算
	    if (!this.isSetData) {
	      // 确定是向上还是向下滚动
	      this.isLeft = curWid.offsetCol < 0;
	      // 确定下次focus子组件的origin
	      if (this.isLeft && this.origin > 0) {
	        this.origin--;
	      } else if (!this.isLeft && this.origin < this.originArr.length - 1) {
	        this.origin++;
	      }
	    }

	    // 选中的组件的中心点应在的位置
	    this.focsedCX = this.originArr[this.origin];
	    // 确定滚动结束后当前选中的行左右各应该有多少列
	    // 没有设置originSize的情况
	    if (this.originSize === 1) {
	      this.leftCol = Math.floor(this.col / 2);
	      this.rightCol = Math.floor(this.col / 2);
	      var curDataCol = Math.floor(this.dataIndex / this.row);
	      var lastDataCol = Math.floor((this.data.length - 1) / this.row);
	      var tempFocsedCX = this.focsedCX;
	      // 到达右部的情况
	      var rightOffset = (lastDataCol - curDataCol) * this.colWidth + this.colWidth / 2;
	      if (rightOffset < tempFocsedCX) {
	        this.focsedCX = this.conWidth - rightOffset;
	        this.rightCol = lastDataCol - curDataCol;
	        this.leftCol = this.col - 1 - this.rightCol;
	      }
	      // 到达左部的情况，如果同时到达左部和右部，则按左部算
	      var leftOffset = curDataCol * this.colWidth + this.colWidth / 2;
	      var listWidth = (lastDataCol + 1) * this.colWidth;
	      if (leftOffset < tempFocsedCX || listWidth < this.conWidth) {
	        this.focsedCX = leftOffset;
	        this.leftCol = curDataCol;
	        this.rightCol = this.col - 1 - this.leftCol;
	        return;
	      }
	      // 设置originSize的情况
	    } else {
	        this.leftCol = this.origin + 1;
	        this.rightCol = this.originSize - this.origin;
	        // 到达左部的情况
	        if (this.dataIndex < this.row) {
	          this.leftCol = 0;
	          this.rightCol = this.col - 1;
	          return;
	        }
	        // 到达右部的情况
	        if (Math.floor(this.dataIndex / this.row) === Math.floor((this.data.length - 1) / this.row)) {
	          this.leftCol = this.col - 1;
	          this.rightCol = 0;
	        }
	      }
	  };

	  // 根据Grid的状态计算每个widget自身的状态
	  // curWid：当前焦点子组件
	  // 纵向Grid使用

	  Grid.prototype._computeAllWidgetStatus_v = function _computeAllWidgetStatus_v(curWid) {
	    var curWidRow = curWid.row;
	    var curDataRow = Math.floor(this.dataIndex / this.col);
	    this._computeRowWidgetStatus_v(curWidRow, curDataRow, 0);
	    for (var i = -1; i >= -this.upRow; i--) {
	      this._computeRowWidgetStatus_v(curWidRow, curDataRow, i);
	    }
	    for (var i = 1; i <= this.downRow; i++) {
	      this._computeRowWidgetStatus_v(curWidRow, curDataRow, i);
	    }
	  };

	  // 横向Grid使用

	  Grid.prototype._computeAllWidgetStatus_h = function _computeAllWidgetStatus_h(curWid) {
	    var curWidCol = curWid.col;
	    var curDataCol = Math.floor(this.dataIndex / this.row);
	    this._computeColWidgetStatus_h(curWidCol, curDataCol, 0);
	    for (var i = -1; i >= -this.leftCol; i--) {
	      this._computeColWidgetStatus_h(curWidCol, curDataCol, i);
	    }
	    for (var i = 1; i <= this.rightCol; i++) {
	      this._computeColWidgetStatus_h(curWidCol, curDataCol, i);
	    }
	  };

	  // 设置某行widget的状态，纵向Grid使用
	  // 如：动画、位置、whichData等

	  Grid.prototype._computeRowWidgetStatus_v = function _computeRowWidgetStatus_v(curWidRow, curDataRow, offsetRow) {
	    //console.log("curWidRow == " + curWidRow + "offsetRow == " + offsetRow + "this.row ==  " + this.row);
		  var widRow = (curWidRow + offsetRow + this.row) % this.row;
	    var dataRow = curDataRow + offsetRow;
	    for (var i = 0; i < this.col; i++) {
	      var widget = this.childWidgets[this.col * widRow + i];
	      var whichData = this.col * dataRow + i;
	      var opacityAfterAnimation = 1;
	      if (whichData >= this.data.length || whichData < 0) {
	        opacityAfterAnimation = 0;
	      }
	      widget.whichData = whichData;
	      widget.whichDataRow = dataRow;
		  if (this.isSetData) {
	        widget.offset = this.focsedCY + offsetRow * this.rowHeight - widget.oriCenteY;
	        widget.con.parentNode.style.top = widget.offset + 'px';
	        widget.con.style.opacity = opacityAfterAnimation;
			  if(i==0){
				  //console.log("offsetRow = " + offsetRow + " widget.oriCenteY = " + widget.oriCenteY + " widget.offsetRow == " + widget.offsetRow);
				  //console.log("nexOffset == " + nexOffset + " opacityAfterAnimation == " + opacityAfterAnimation);
			  }
	        widget.offsetRow = offsetRow;
	      } else {
	        var nexOffset = this.focsedCY + offsetRow * this.rowHeight - widget.oriCenteY;
	        widget.futureOffset = nexOffset;
	        widget.animationArr.push({
	          offset: nexOffset,
	          jump: widget.offsetRow * offsetRow < 0,
	          opacity: opacityAfterAnimation
	        });
			  //if(i==0){
				//  console.log("offsetRow = " + offsetRow + " widget.oriCenteY = " + widget.oriCenteY + " widget.offsetRow == " + widget.offsetRow);
				//  console.log("nexOffset == " + nexOffset + " opacityAfterAnimation == " + opacityAfterAnimation);
			  //}
	        widget.offsetRow = offsetRow;
	      }
	    }
	  };

	  // 设置某行widget的状态，横向Grid使用
	  // 如：动画、位置、whichData等

	  Grid.prototype._computeColWidgetStatus_h = function _computeColWidgetStatus_h(curWidCol, curDataCol, offsetCol) {
	    var widCol = (curWidCol + offsetCol + this.col) % this.col;
	    var dataCol = curDataCol + offsetCol;
	    for (var i = 0; i < this.row; i++) {
	      var widget = this.childWidgets[this.row * widCol + i];
	      var whichData = dataCol * this.row + i;
	      var opacityAfterAnimation = 1;
	      if (whichData >= this.data.length || whichData < 0) {
	        opacityAfterAnimation = 0;
	      }
	      widget.whichData = whichData;
	      widget.whichDataCol = dataCol;
	      if (this.isSetData) {
	        widget.offset = this.focsedCX + offsetCol * this.colWidth - widget.oriCenteX;
	        widget.con.parentNode.style.left = widget.offset + 'px';
	        widget.con.style.opacity = opacityAfterAnimation;
	        widget.offsetCol = offsetCol;
	      } else {
	        var nexOffset = this.focsedCX + offsetCol * this.colWidth - widget.oriCenteX;
	        widget.futureOffset = nexOffset;
	        widget.animationArr.push({
	          offset: nexOffset,
	          jump: widget.offsetCol * offsetCol < 0,
	          opacity: opacityAfterAnimation
	        });
	        widget.offsetCol = offsetCol;
	      }
	    }
	  };

	  // 如果是还未开始动画，计算动画延迟且触发动画

	  Grid.prototype._triggerWidgetsAnimation_v = function _triggerWidgetsAnimation_v() {
	    for (var i = 0; i < this.row; i++) {
	      var widget = this.widgetArr[i][0];
	      if (widget.animationArr.length !== 1) {
	        return;
	      }
	      this['_startScroll_' + this.dir](widget);
	    }
	  };

	  // 如果是还未开始动画，计算动画延迟且触发动画

	  Grid.prototype._triggerWidgetsAnimation_h = function _triggerWidgetsAnimation_h() {
	    for (var i = 0; i < this.col; i++) {
	      var widget = this.widgetArr[i][0];
	      if (widget.animationArr.length !== 1) {
	        return;
	      }
	      this['_startScroll_' + this.dir](widget);
	    }
	  };

	  Grid.prototype._startScroll_v = function _startScroll_v(widget, speedup) {
	    var _this = this;

	    var rowWidgets = this.widgetArr[widget.row];
	    for (var i = 0, l = rowWidgets.length; i < l; i++) {
	      var tempWidget = rowWidgets[i];
	      var _animation = tempWidget.animationArr[0];
	      if (_animation.jump) {
	        if (this.noEmpty) {
	          var item = this.data[tempWidget.whichData];
	          if (item) {
	            this.itemRender(tempWidget.getDOMNode(), item);
	            tempWidget.isEmpty = false;
	          }
	        } else if (!tempWidget.isEmpty) {
	          this.itemRender(tempWidget.getDOMNode());
	          tempWidget.isEmpty = true;
	        }
	      }
	    }
	    var endCb = function endCb() {
	      for (var i = 0, l = rowWidgets.length; i < l; i++) {
	        var tempWidget = rowWidgets[i];
	        var preAnimation = tempWidget.animationArr.shift();
	        tempWidget.offset = preAnimation.offset;
	        tempWidget.con.style.opacity = preAnimation.opacity;
	      }
	      if (widget.animationArr.length > 0) {
	        _this._startScroll_v(widget, true);
	      } else {
	        if (_this.scrolling && widget.row === 0) {
	          _this.scrolling = false;
	          _this.fire(new _event2['default']('scrollend', _this));
	        }
	      }
	    };
	    this.stopSwitch = widget.animationArr.length >= 2;
	    var animation = widget.animationArr[0];
	    if (animation.offset !== widget.offset && !animation.jump) {
	      if (!this.scrolling) {
	        this.scrolling = true;
	        this.fire(new _event2['default']('scrollstart', this, { distance: animation.offset - widget.offset }));
	      }
	    }
	    (0, _animate2['default'])({
	      dom: widget.con.parentNode,
	      style: this.style,
	      start: animation.jump ? animation.offset : widget.offset,
	      end: animation.offset,
	      duration: speedup ? this.speedupDuration : this.duration,
	      easing: speedup ? this.speedupEasing : this.easing,
	      cb: endCb
	    });
	  };

	  Grid.prototype._startScroll_h = function _startScroll_h(widget, speedup) {
	    var _this2 = this;

	    var colWidgets = this.widgetArr[widget.col];
	    for (var i = 0, l = colWidgets.length; i < l; i++) {
	      var tempWidget = colWidgets[i];
	      var _animation2 = tempWidget.animationArr[0];
	      if (_animation2.jump) {
	        if (this.noEmpty) {
	          var item = this.data[tempWidget.whichData];
	          if (item) {
	            this.itemRender(tempWidget.getDOMNode(), item);
	            tempWidget.isEmpty = false;
	          }
	        } else if (!tempWidget.isEmpty) {
	          this.itemRender(tempWidget.getDOMNode());
	          tempWidget.isEmpty = true;
	        }
	      }
	    }
	    var endCb = function endCb() {
	      for (var i = 0, l = colWidgets.length; i < l; i++) {
	        var tempWidget = colWidgets[i];
	        var preAnimation = tempWidget.animationArr.shift();
	        tempWidget.offset = preAnimation.offset;
	        tempWidget.con.style.opacity = preAnimation.opacity;
	      }
	      if (widget.animationArr.length > 0) {
	        _this2._startScroll_h(widget, true);
	      } else {
	        if (_this2.scrolling && widget.col === 0) {
	          _this2.scrolling = false;
	          _this2.fire(new _event2['default']('scrollend', _this2));
	        }
	      }
	    };
	    this.stopSwitch = widget.animationArr.length >= 2;
	    var animation = widget.animationArr[0];
	    if (animation.offset !== widget.offset && !animation.jump) {
	      if (!this.scrolling) {
	        this.scrolling = true;
	        this.fire(new _event2['default']('scrollstart', this, { distance: animation.offset - widget.offset }));
	      }
	    }
	    (0, _animate2['default'])({
	      dom: widget.con.parentNode,
	      style: this.style,
	      start: animation.jump ? animation.offset : widget.offset,
	      end: animation.offset,
	      duration: speedup ? this.speedupDuration : this.duration,
	      easing: speedup ? this.speedupEasing : this.easing,
	      cb: endCb
	    });
	  };

	  Grid.prototype.scrollendDefault = function scrollendDefault(e) {
	    if (e.isDefaultPrevented()) {
	      return;
	    }
	    if (this.scrolling) {
	      return;
	    }
	    this['_toggleDelay_' + this.dir](0);
	  };

	  Grid.prototype.scrollstartDefault = function scrollstartDefault(e) {
	    if (e.isDefaultPrevented()) {
	      return;
	    }
	    this['_toggleDelay_' + this.dir](e.distance);
	    this.loadContentTimeout && clearTimeout(this.loadContentTimeout);
	    // Blitz内核提供的禁止图片加载的方法，优化动画
	    window.stopImgLoading && window.stopImgLoading();
	  };

	  // 开始或者结束delay状态
	  // @param {Number} moveDistance 此次焦点滚动的距离，根据改距离确定delay幅度

	  Grid.prototype._toggleDelay_v = function _toggleDelay_v() {
	    var _this3 = this;

	    var moveDistance = arguments.length <= 0 || arguments[0] === undefined ? 0 : arguments[0];

	    var focusedWidget = this.getFocusedChildWidget() || this.getCachedChildWidget();
	    if (!focusedWidget) {
	      return;
	    }
	    var focusCol = focusedWidget.col;
	    for (var i = 0; i < this.col; i++) {
	      for (var j = 0; j < this.row; j++) {
	        var widget = this.widgetArr[j][i];
	        var delayOffset = -(moveDistance * this.delay * Math.abs(widget.col - focusCol * this.delayStyle));
	        var aniEndCb = null;
	        if (delayOffset === 0 && i === 0 && j === 0) {
	          aniEndCb = function () {
	            _this3.loadContent();
	          };
	        }
	        (0, _animate2['default'])({
	          dom: widget.con,
	          style: this.style,
	          start: widget.delayOffset || 0,
	          end: delayOffset,
	          duration: this.duration,
	          easing: 'ease-out',
	          cb: aniEndCb
	        });
	        widget.delayOffset = delayOffset;
	      }
	    }
	  };

	  // 开始或者结束delay状态
	  // @param {Number} moveDistance 此次焦点滚动的距离，根据改距离确定delay幅度

	  Grid.prototype._toggleDelay_h = function _toggleDelay_h() {
	    var _this4 = this;

	    var moveDistance = arguments.length <= 0 || arguments[0] === undefined ? 0 : arguments[0];

	    var focusedWidget = this.getFocusedChildWidget() || this.getCachedChildWidget();
	    if (!focusedWidget) {
	      return;
	    }
	    var focusRow = focusedWidget.row;
	    for (var i = 0; i < this.row; i++) {
	      for (var j = 0; j < this.col; j++) {
	        var widget = this.widgetArr[j][i];
	        var delayOffset = -(moveDistance * this.delay * Math.abs(widget.row - focusRow * this.delayStyle));
	        var aniEndCb = null;
	        if (delayOffset === 0 && i === 0 && j === 0) {
	          aniEndCb = function () {
	            _this4.loadContent();
	          };
	        }
	        (0, _animate2['default'])({
	          dom: widget.con,
	          style: this.style,
	          start: widget.delayOffset || 0,
	          end: delayOffset,
	          duration: this.duration,
	          easing: 'ease-out',
	          cb: aniEndCb
	        });
	        widget.delayOffset = delayOffset;
	      }
	    }
	  };

	  Grid.prototype.setItemRender = function setItemRender(fun) {
	    this.itemRender = function (dom, item) {
	      fun(dom, item);
	      // Blitz提供的加载文字的方法，用于避免滚动过程中文字加载不全的问题
	      dom.createTextGraphics && dom.createTextGraphics();
	    };
	    return this;
	  };

	  Grid.prototype.addData = function addData(data) {
	    if (!Array.isArray(data)) {
	      return;
	    }
	    var newData = this.data.concat(data);
	    var dataIndex = this.focused ? this.getFocusedChildWidget().whichData : this.dataIndex;
	    this.setData(newData, dataIndex, this.origin);
	    return this;
	  };

	  Grid.prototype.setData = function setData(data, index, origin) {
	    if (Array.isArray(data)) {
	      this.data = data.concat([]);
	    }
	    this.isSetData = true;
	    this.allDataCol = Math.floor(this.data.length / this.row);
	    this.allDataRow = Math.floor(this.data.length / this.col);
	    if (index !== undefined && index < this.data.length) {
	      this.dataIndex = index;
	    } else {
	      this.dataIndex = 0;
	    }
	    this.origin = this['_getSetDataOrigin_' + this.dir](this.data.length, this.dataIndex, origin);
	    var nexWid = this['_getWidgetByDataIndex_' + this.dir](this.dataIndex);
	    this['_computeGridStatus_' + this.dir](nexWid);
	    this['_computeAllWidgetStatus_' + this.dir](nexWid);
	    nexWid.dataIndex = this.dataIndex;
	    if (this.focused) {
	      nexWid.focus(true, true);
	    } else {
	      nexWid.cache();
	    }
	    this.curWid = nexWid;
	    this.loadContent();
	    this.isSetData = false;
	    return this;
	  };

	  // 根据dataIndex获取当前对应的是哪个widget

	  Grid.prototype._getWidgetByDataIndex_v = function _getWidgetByDataIndex_v(dataIndex) {
	    return this.childWidgets[Math.floor(dataIndex / this.col) % this.row * this.col + dataIndex % this.col];
	  };

	  // 根据dataIndex获取当前对应的是哪个widget

	  Grid.prototype._getWidgetByDataIndex_h = function _getWidgetByDataIndex_h(dataIndex) {
	    return this.childWidgets[Math.floor(dataIndex / this.row) % this.col * this.row + dataIndex % this.row];
	  };

	  // 根据数据长度，当前setData的index及origin返回合适的origin

	  Grid.prototype._getSetDataOrigin_v = function _getSetDataOrigin_v(dataLength, index, origin) {
	    if (origin === undefined || origin > this.originSize) {
	      origin = 0;
	    }
	    var row = Math.floor(this.dataIndex / this.col);
	    var lastRow = Math.floor((this.data.length - 1) / this.col);
	    // 最后的几行item有最小的origin限制
	    if (lastRow - row < this.originSize) {
	      var minOrigin = row + this.originSize - lastRow - 1;
	      if (minOrigin >= 0 && origin < minOrigin) {
	        origin = minOrigin;
	      }
	    }
	    // 最前的几个item的origin有最大的origin限制
	    if (row < this.originSize) {
	      var maxOrigin = row;
	      if (origin > maxOrigin) {
	        origin = maxOrigin;
	      }
	    }
	    return origin;
	  };

	  // 根据数据长度，当前setData的index及origin返回合适的origin

	  Grid.prototype._getSetDataOrigin_h = function _getSetDataOrigin_h(dataLength, index, origin) {
	    if (origin === undefined || origin > this.originSize) {
	      origin = 0;
	    }
	    var col = Math.floor(this.dataIndex / this.row);
	    var lastCol = Math.floor((this.data.length - 1) / this.row);
	    // 最后的几列item有最小的origin限制
	    if (lastCol - col < this.originSize) {
	      var minOrigin = col + this.originSize - lastCol - 1;
	      if (minOrigin >= 0 && origin < minOrigin) {
	        origin = minOrigin;
	      }
	    }
	    // 最前的几个item的origin有最大的origin限制
	    if (col < this.originSize) {
	      var maxOrigin = col;
	      if (origin > maxOrigin) {
	        origin = maxOrigin;
	      }
	    }
	    return origin;
	  };

	  // 加载内容

	  Grid.prototype.loadContent = function loadContent() {
	    if (this.scrolling) {
	      return;
	    }
	    for (var i = 0, _length = this.childWidgets.length; i < _length; i++) {
	      var widget = this.childWidgets[i];
	      // 如果是setData调用，那么需要强制重新渲染item
			console.log("widget.isEmpty = " + widget.isEmpty + " this.isSetData = " + this.isSetData);
	      if (widget.isEmpty || this.isSetData) {
	        var item = this.data[widget.whichData];
	        this.itemRender && this.itemRender(widget.getDOMNode(), item);
	        widget.isEmpty = false;
	      }
	    }
	    // Blitz内核提供的恢复图片加载的方法
	    window.resumeImgLoading && window.resumeImgLoading();
	    this.fire(new _event2['default']('contentloaded', this));
	  };

	  // 更改Grid的内容
	  // 参数同数组的splice

	  Grid.prototype.splice = function splice() {
	    Array.prototype.splice.apply(this.data, arguments);
	    this.isSetData = true;
	    this.loadContent();
	    this.isSetData = false;
	  };

	  Grid.prototype.getEvents = function getEvents() {
	    return _Widget.prototype.getEvents.call(this).concat(['reachend', 'contentloaded']);
	  };

	  return Grid;
	})(_widget2['default']);

	exports['default'] = Grid;
	module.exports = exports['default'];

/***/ },
/* 9 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, '__esModule', {
	  value: true
	});

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }

	function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

	var _engine = __webpack_require__(1);

	var _engine2 = _interopRequireDefault(_engine);

	var _widget = __webpack_require__(3);

	var _widget2 = _interopRequireDefault(_widget);

	var _event = __webpack_require__(2);

	var _event2 = _interopRequireDefault(_event);

	var _animate = __webpack_require__(6);

	var _animate2 = _interopRequireDefault(_animate);

	// TODO:补充注释

	var Grille = (function (_Widget) {
	  _inherits(Grille, _Widget);

	  function Grille(container) {
	    _classCallCheck(this, Grille);

	    _Widget.call(this, container);
	    this._init();
	  }

	  Grille.prototype._init = function _init() {
	    var _this = this;

	    // this.horizontal = this.options.cfg.dir === 'h';
	    // 创建内部的list
	    this.listDom = document.createElement('div');
	    this.listDom.style.position = 'relative';
	    this.listDom.style.width = '100%';
	    this.con.innerHTML = '';
	    this.con.appendChild(this.listDom);
	    this.duration = this.options.cfg.duration !== undefined ? parseFloat(this.options.cfg.duration) : 0.3;
	    this.delay = this.options.cfg.delay !== undefined ? parseFloat(this.options.cfg.delay) : 0.1;
	    this.easing = this.options.cfg.easing ? this.options.cfg.easing : 'ease-out';
	    this.bottomPadding = this.options.cfg.bottom_padding !== undefined ? parseFloat(this.options.cfg.bottom_padding) : 0;
	    this.visibleRow = this.options.cfg.visible_row !== undefined ? parseInt(this.options.cfg.visible_row) : 5;
	    this.listDom.style.transition = 'transform ' + this.duration + 's ' + this.easing;
	    this.listDom.addEventListener('transitionend', function (e) {
	      if (e.target === _this.listDom) {
	        _this.fire(new _event2['default']('scrollend', _this));
	      }
	    });
	    this.getWidgetRect();
	    this.align = this.rect.height / 2;
	    this.offset = 0;
	    this._reset();
	  };

	  Grille.prototype._reset = function _reset() {
	    // 记录最后一个item是第几行第几列
	    this.lastWidgetRow = 0;
	    this.lastWidgetCol = 0;
	    this.lastWidgetCenter = 0;
	    this.listHeight = 0;
	    // 用二维数组记录子widget，便于查找
	    this.childrenArr = [];
	    // 只记录子Widget
	    this.childWidgets = [];
	    // 记录所有类型的子代
	    this.childItems = [];
	    this.focusPos = {
	      row: 0,
	      col: 0
	    };
	  };

	  Grille.prototype.setData = function setData(data, index) {
	    var _this2 = this;

	    this.isSetData = true;
	    if (this.childItems.length == 0) {
	      this.listDom.innerHTML = '';
	      this._reset();
	      this.dataIndex = index !== undefined ? index : 0;
	      this.data = [].concat(data);
	      this._renderChildren();
	      return;
	    }
	    var transitionEndSetted = false;
	    for (var i = 0; i < this.childItems.length; i++) {
	      var item = this.childItems[i];
	      if (item.con && item.visible) {
	        item.con.style.transform = 'scale3d(0.3,0.3,0.3)';
	        if (!transitionEndSetted) {
	          transitionEndSetted = true;
	          item.con.addEventListener('transitionend', function (e) {
	            _this2.listDom.innerHTML = '';
	            _this2._reset();
	            _this2.dataIndex = index !== undefined ? index : 0;
	            _this2.data = [].concat(data);
	            _this2._renderChildren();
	          });
	        }
	      }
	    }
	  };

	  Grille.prototype.addData = function addData(data) {
	    this.data = this.data.concat(data);
	    this._renderChildren();
	  };

	  Grille.prototype.setItemRender = function setItemRender(itemRender) {
	    this.itemRender = itemRender;
	  };

	  Grille.prototype._renderChildren = function _renderChildren() {
	    var _this3 = this;

	    // renderChildren时需要同时有data且有itemRender
	    if (!this.data || !this.itemRender) {
	      return;
	    }
	    this.isSetData && (this.listDom.style.visibility = 'hidden');

	    var _loop = function (i) {
	      var tempData = _this3.data[i];
	      var dom = _this3.itemRender(tempData);
	      // 如果render返回的是string，那么将string parse成dom对象
	      if (typeof dom === 'string') {
	        var children = _this3.parseDom(dom);
	        if (children.length > 1) {
	          console.error('[FocusEngine_Error]Grille组件的itemRender返回的字符串必须是可解析成一个dom对象。');
	          return 'continue';
	        }
	        dom = children[0];
	      }
	      var lazyDom = dom.querySelector('.grille-lazyload');
	      lazyDom && dom.removeChild(lazyDom);
	      _this3.listDom.appendChild(dom);
	      if (!dom.getAttribute('fe-role')) {
	        _this3.childItems.push(dom);
	        return 'continue';
	      }
	      var widget = _engine2['default'].createWidget(dom);
	      _this3.addChildWidget(widget);
	      _this3.childItems.push(widget);
	      widget.data = tempData;
	      widget.index = i;
	      widget.lazyDom = lazyDom;
	      widget.getWidgetRectAsync(function (widgetRect) {
	        // 计算正常情况下，该widget获取焦点时整个列表的偏移量
	        // 初始情况下，组件中心点距离容器top的距离
	        widget.oriOffset = widgetRect.centerY - _this3.rect.top - _this3.offset;
	        if (_this3.listHeight < widgetRect.bottom - _this3.rect.top - _this3.offset + _this3.bottomPadding) {
	          _this3.listHeight = widgetRect.bottom - _this3.rect.top - _this3.offset + _this3.bottomPadding;
	        }
	        if (!_this3.lastWidgetCenter) {
	          // 第一个widget时
	          widget.row = _this3.lastWidgetRow;
	          widget.col = _this3.lastWidgetCol;
	          _this3.lastWidgetCenter = widgetRect.centerY;
	          _this3.childrenArr[_this3.lastWidgetRow] = [widget];
	        } else if (widgetRect.centerY - _this3.offset === _this3.lastWidgetCenter) {
	          // 同一行的情况
	          widget.row = _this3.lastWidgetRow;
	          _this3.lastWidgetCol++;
	          widget.col = _this3.lastWidgetCol;
	          _this3.childrenArr[_this3.lastWidgetRow].push(widget);
	        } else if (widgetRect.centerY - _this3.offset > _this3.lastWidgetCenter) {
	          // 换行的情况
	          _this3.lastWidgetRow++;
	          widget.row = _this3.lastWidgetRow;
	          _this3.lastWidgetCol = 0;
	          widget.col = _this3.lastWidgetCol;
	          _this3.lastWidgetCenter = widgetRect.centerY - _this3.offset;
	          _this3.childrenArr[_this3.lastWidgetRow] = [widget];
	        }
	        if (widget.row <= _this3.visibleRow) {
	          widget.visible = true;
	          widget.con.style.transition = 'transform ' + _this3.duration * 0.8 + 's ' + _this3.easing;
	        }
	        if (i === _this3.data.length - 1) {
	          _this3.focused && _this3.childItems[_this3.dataIndex].focus();
	          if (_this3.isSetData) {
	            _this3.listDom.style.visibility = 'visible';
	            var setWidget = _this3.childItems[_this3.dataIndex];
	            _this3.loadContent();
	            _this3._doScroll(setWidget);
	            _this3.setCachedChildWidget(setWidget);
	          }
	        }
	      });
	    };

	    for (var i = this.childItems.length; i < this.data.length; i++) {
	      var _ret = _loop(i);

	      if (_ret === 'continue') continue;
	    }
	  };

	  Grille.prototype.focusDefault = function focusDefault(e) {
	    _Widget.prototype.focusDefault.call(this, e);
	    if (e.target === this) {
	      return;
	    }
	    if (this.isSetData) {
	      return;
	    }
	    this.dataIndex = e.target.index;
	    this._doScroll(e.target);
	  };

	  Grille.prototype._doScroll = function _doScroll(curWidget) {
	    var _this4 = this;

	    this.focusPos.row = curWidget.row;
	    this.focusPos.col = curWidget.col;
	    // 如果列表高度小于容器高度，不滚动
	    if (this.listHeight < this.rect.height) {
	      return;
	    }
	    var offset = this.align - curWidget.oriOffset;
		  console.log("offset == " + offset);
		  // 到达顶部的情况
	    if (offset > 0) {
	      offset = 0;
	    }
	    // 到达底部的情况
	    if (this.listHeight - curWidget.oriOffset < this.rect.height - this.align) {
	      offset = this.rect.height - this.listHeight;
	    }
	    // 配置位置的情况
	    if (curWidget.data.align !== undefined) {
	      offset = this.align - curWidget.oriOffset;
	    }
	    // 如果同一行，不滚动
	    if (this.offset === offset && !this.isSetData) {
	      return;
	    }
		  console.log("offset2 == " + offset);
	    if (this.isSetData) {
			//
	      this.listDom.style.transition = '';
	      this.listDom.style.transform = 'translateY(' + (offset + this.rect.height) + 'px)';
	      this.offset = offset + this.rect.height;
	      setTimeout(function () {
	        _this4.listDom.style.transition = 'transform ' + _this4.duration + 's ' + _this4.easing;
	        _this4.listDom.style.transform = 'translateY(' + offset + 'px)';
	        var des = -_this4.rect.height / 3;
	        _this4.offset = offset;
	        !_this4.isScrolling && _this4.fire(new _event2['default']('scrollstart', _this4, { des: des }));
	        _this4.isSetData = false;
	      }, 300);
	    } else {
	      this.listDom.style.transition = 'transform ' + this.duration + 's ' + this.easing;
	      this.listDom.style.transform = 'translateY(' + offset + 'px)';
	      var des = offset - this.offset;
	      this.offset = offset;
	      !this.isScrolling && this.fire(new _event2['default']('scrollstart', this, { des: des }));
	    }
	  };

	  Grille.prototype.keydownDefault = function keydownDefault(e) {
	    var curRow = this.focusPos.row;
	    var curCol = this.focusPos.col;
	    if (e.keyCode === _event2['default'].VK_UP && curRow > 0) {
	      curRow--;
	      if (curCol >= this.childrenArr[curRow].length) {
	        curCol = this.childrenArr[curRow].length - 1;
	      }
	      e.preventDefault();
	    }
	    if (e.keyCode === _event2['default'].VK_DOWN && curRow == this.lastWidgetRow - 1) {
	      this.fire(new _event2['default']('reachend', this));
	    }
	    if (e.keyCode === _event2['default'].VK_DOWN && curRow < this.lastWidgetRow) {
	      curRow++;
	      if (curCol >= this.childrenArr[curRow].length) {
	        curCol = this.childrenArr[curRow].length - 1;
	      }
	      e.preventDefault();
	    }
	    if (e.keyCode === _event2['default'].VK_LEFT && curCol > 0) {
	      curCol--;
	      e.preventDefault();
	    }
	    if (e.keyCode === _event2['default'].VK_RIGHT && curCol < this.childrenArr[curRow].length - 1) {
	      curCol++;
	      e.preventDefault();
	    }
	    if (curRow === this.focusPos.row && curCol === this.focusPos.col) {
	      return;
	    } else {
	      this.focusPos.row = curRow;
	      this.focusPos.col = curCol;
	      var tempWidget = this.childrenArr[curRow][curCol];
	      tempWidget.focus();
	    }
	  };

	  Grille.prototype.scrollstartDefault = function scrollstartDefault(e) {
	    this.isScrolling = true;
	    // Blitz内核提供的禁止图片加载的方法，优化动画
	    window.stopImgLoading && window.stopImgLoading();
	    clearTimeout(this.loadContentTimeout);
	    var curWidget = this.childItems[this.dataIndex];
	    for (var i = 0; i < this.childWidgets.length; i++) {
	      var widget = this.childWidgets[i];
	      var delay = -Math.abs(widget.col - curWidget.col) * e.des * this.delay;
	      widget.con.style.transform = 'translateY(' + delay + 'px)';
	    }
	  };

	  Grille.prototype.scrollendDefault = function scrollendDefault(e) {
	    var _this5 = this;

	    this.isScrolling = false;
	    var curWidget = this.childItems[this.dataIndex];
	    for (var i = 0; i < this.childWidgets.length; i++) {
	      var widget = this.childWidgets[i];
	      var loadRowMax = Math.floor(this.visibleRow / 2);
	      if (Math.abs(widget.row - curWidget.row) <= loadRowMax) {
	        widget.con.style.transition = 'transform ' + this.duration * 0.8 + 's ' + this.easing;
	        widget.visible = true;
	      } else if (widget.visible) {
	        widget.con.style.transition = '';
	        widget.visible = false;
	      }
	      widget.con.style.transform = '';
	    }
	    this.loadContentTimeout = setTimeout(function () {
	      _this5.loadContent();
	    }, 500);
	  };

	  Grille.prototype.loadContent = function loadContent() {
	    for (var i = 0; i < this.childWidgets.length; i++) {
	      var widget = this.childWidgets[i];
	      if (widget.lazyDom && widget.visible && !widget.lazyLoaded) {
	        widget.con.appendChild(widget.lazyDom);
	        widget.lazyLoaded = true;
	      } else if (widget.lazyDom && !widget.visible && widget.lazyLoaded) {
	        widget.con.removeChild(widget.lazyDom);
	        widget.lazyLoaded = false;
	      }
	    }
	    // Blitz内核提供的恢复图片加载的方法
	    window.resumeImgLoading && window.resumeImgLoading();
	    this.fire(new _event2['default']('contentloaded', this));
	  };

	  Grille.prototype.getEvents = function getEvents() {
	    return _Widget.prototype.getEvents.call(this).concat(['scrollstart', 'scrollend', 'contentloaded', 'reachend']);
	  };

	  return Grille;
	})(_widget2['default']);

	exports['default'] = Grille;
	module.exports = exports['default'];

/***/ }
/******/ ]);